/*
 *   compiler/back_ends/c++_gen/gen_code.c - routines for printing C++ code from type trees
 *
 *   assumes that the type tree has already been run through the
 *   c++ type generator (c++_gen/types.c).
 *
 *  This was hastily written - it has some huge routines in it.
 *  Needs a lot of cleaning up and modularization...
 *
 * Mike Sample
 * 92
 * Copyright (C) 1991, 1992 Michael Sample
 *           and the University of British Columbia
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * $Header: /usr/app/odstb/CVS/snacc/compiler/back-ends/c++-gen/gen-code.c,v 1.12 1997/02/28 13:39:53 wan Exp $
 * $Log: gen-code.c,v $
 * Revision 1.12  1997/02/28 13:39:53  wan
 * Modifications collected for new version 1.3: Bug fixes, tk4.2.
 *
 * Revision 1.11  1997/02/16 15:14:06  rj
 * made return *this after calling abort()'' a compile time option.
 *
 * Revision 1.10  1997/02/16 12:46:31  rj
 * use the TIME_WITH_SYS_TIME flag (checked and generated by configure).
 * return *this after calling abort() for compilers that don't know about this volatile function.
 * comment out unused parameters, the compiler otherwise may complain.
 *
 * Revision 1.9  1995/09/07  20:47:32  rj
 * deep copying assingment operators added.
 *
 * Revision 1.8  1995/09/07  19:25:27  rj
 * PrintCxxCode(): boolean genMeta changed to enum type MetaNameStyle. used globally in printMetaG.
 *
 * set Tcl's errorCode variable.
 *
 * Revision 1.7  1995/08/17  15:00:06  rj
 * the PDU flag belongs to the metacode, not only to the tcl interface. (type and variable named adjusted)
 *
 * Revision 1.6  1995/07/27  10:52:28  rj
 * include config.h before using its #define's :-)
 *
 * file name has been shortened for redundant part: c++-gen/gen-c++-code -> c++-gen/gen-code.
 *
 * functions used only locally made static.
 *
 * #if TCL ... #endif wrapped into #if META ... #endif, both here and in generated files.
 *
 * code changes to allow for more than one PDU (meta code), e.g. generate -create() functions.
 *
 * generate additional TclUnsetVal() function to delete OPTIONAL members and SEQUENCE OF and SET OF list elements.
 *
 * _getref() gets an additional optional argument to faciliate the different member access semantics of TclGetVal() and TclSetVal().
 *
 * the list functions Append(), Prepend(), InsertBefore() and InsertAfter() now set the current element to the element just inserted.
 *
 * changed `_' to `-' in file names.
 *
 * Revision 1.5  1995/02/18  14:45:16  rj
 * tried to make the print function's output a little more readable. [kho]
 *
 * Revision 1.4  1994/10/08  03:19:24  rj
 * since i was still irritated by cpp standing for c++ and not the C preprocessor, i renamed them to cxx (which is one known suffix for C++ source files). since the standard #define is __cplusplus, cplusplus would have been the more obvious choice, but it is a little too long.
 *
 * turned the functions order upside down to get rid of those annoying declarations.
 *
 * turned character pointers into constant character arrays.
 *
 * code for meta structures added (provides information about the generated code itself).
 *
 * code for Tcl interface added (makes use of the above mentioned meta code).
 *
 * instead of being a no-op, the no-arg-constructors (that get used by Clone()) do something useful now, namely:
 * - initialize the pointer in a choice union. (the destruktor may try to free the bogus pointer).
 * - for the same reason: initialize pointers in sequences and sets.
 *
 * to complement the destructors, T::T (const T&) and T &T::operator = (const T &) have been added to override the defaults supplied by the compiler.
 * reason: simple pointer duplication may lead to unreferenced objects and to objects referenced more than once (on which the destructors delete may choke).
 *
 * virtual inline functions (the destructor and the Clone() function) moved from inc/*.h to src/*.C because g++ turns every one of them into a static non-inline function in every file where the .h file gets included.
 *
 * made Print() const (and some other, mainly comparison functions).
 *
 * Revision 1.3  1994/09/01  00:16:29  rj
 * change of IBM ENC integrated: large inlines turned into normal functions.
 * more portable .h file inclusion.
 *
 * Revision 1.2  1994/08/31  09:49:05  rj
 * for the C++ code generated: turned TRUE/FALSE into true/false;
 * the keyword `struct' had to be removed before AsnListElmt, or gcc 2.6 wouldn't compile the generated code.
 *
 * Revision 1.1  1994/08/28  09:48:01  rj
 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
 *
 */

#include "snacc.h"

#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif

#if STDC_HEADERS || HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <stdio.h>

#include "asn-incl.h"
#include "asn1module.h"
#include "define.h"
#include "mem.h"
#include "lib-types.h"
#include "rules.h"
#include "types.h"
#include "cond.h"
#include "str-util.h"
#include "snacc-util.h"
#include "print.h"
#include "tag-util.h"  /* get GetTags/FreeTags/CountTags/TagByteLen */
#if META
#include "meta.h"
#endif
#include "gen-vals.h"
#include "gen-any.h"
#include "gen-code.h"


static const char	bufTypeNameG[] = "BUF_TYPE";
static const char	lenTypeNameG[] = "AsnLen";
static const char	tagTypeNameG[] = "AsnTag";
static const char	envTypeNameG[] = "ENV_TYPE";
static long int		longJmpValG  = -100;
static const char	baseClassesG[] = ": public AsnType";

static int		printTypesG;
static int		printEncodersG;
static int		printDecodersG;
static int		printPrintersG;
static int		printFreeG;
#if META
static MetaNameStyle	printMetaG;
static MetaPDU		*meta_pdus_G;
#if TCL
static int		printTclG;
#endif
#endif /* META */


static void
PrintHdrComment PARAMS ((hdr, m),
    FILE *hdr _AND_
    Module *m)
{
    time_t now = time (NULL);

    fprintf (hdr, "//   NOTE: this is a machine generated file--editing not recommended\n");
    fprintf (hdr, "//\n");
    fprintf (hdr, "// %s - class definitions for ASN.1 module %s\n", m->cxxHdrFileName, m->modId->name);
    fprintf (hdr, "//\n");
    fprintf (hdr, "//   This file was generated by snacc on %s", ctime (&now));
    fprintf (hdr, "//   UBC snacc by Mike Sample\n");
    fprintf (hdr, "//   A couple of enhancements made by IBM European Networking Center\n"); /* 20.8.93 Thomas Meyer */
    fprintf (hdr, "\n");

} /* PrintHdrComment */

static void
PrintSrcComment PARAMS ((src, m),
    FILE *src _AND_
    Module *m)
{
    time_t now = time (NULL);

    fprintf (src, "//   NOTE: this is a machine generated file--editing not recommended\n");
    fprintf (src, "//\n");
    fprintf (src, "// %s - class member functions for ASN.1 module %s\n", m->cxxSrcFileName, m->modId->name);
    fprintf (src, "//\n");
    fprintf (src, "//   This file was generated by snacc on %s", ctime (&now));
    fprintf (src, "//   UBC snacc written by Mike Sample\n");
    fprintf (src, "//   A couple of enhancements made by IBM European Networking Center\n"); /* 20.8.93 Thomas Meyer */
    fprintf (src, "\n");

} /* PrintSrcComment */


static void
PrintSrcIncludes PARAMS ((src, if_IBM_ENC (srcdb COMMA) mods, m),
    FILE *src _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    ModuleList *mods _AND_
    Module *m)
{
    void *tmp;
    Module *currMod;
#ifdef _IBM_ENC_
    size_t length;
    char *inclstring;
#endif /* _IBM_ENC_ */

    fprintf (src, "#include \"asn-incl.h\"\n");

    tmp = (void *)CURR_LIST_NODE (mods); /* remember curr loc */
    FOR_EACH_LIST_ELMT (currMod, mods)
        fprintf (src, "#include \"%s\"\n", currMod->cxxHdrFileName);
    SET_CURR_LIST_NODE (mods, tmp);

#ifdef _IBM_ENC_
#include "./ibm_editor/print_src_includes.h"
#endif /* _IBM_ENC_ */
} /* PrintSrcIncludes */


static void
PrintTypeDecl PARAMS ((f, td),
    FILE *f _AND_
    TypeDef *td)
{
    switch (td->type->basicType->choiceId)
    {
        case BASICTYPE_COMPONENTSOF:
        case BASICTYPE_SELECTION:
        case BASICTYPE_UNKNOWN:
        case BASICTYPE_MACRODEF:
        case BASICTYPE_MACROTYPE:
            return; /* do nothing */

        default:
            if (IsNewType (td->type))
                fprintf (f, "class %s;\n", td->cxxTypeDefInfo->className);
    }

} /* PrintTypeDecl */


static void
PrintCxxType PARAMS ((hdr, mods, m, r, td, parent, t),
    FILE *hdr _AND_
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *t)
{
    fprintf (hdr, "%s		", t->cxxTypeRefInfo->className);

    if (t->cxxTypeRefInfo->isPtr)
        fprintf (hdr, "*");

} /* PrintCxxType */


#ifdef _IBM_ENC_
static void
PrintCxxTypedb PARAMS ((srcdb, mods, m, r, td, parent, t),
    FILE *srcdb _AND_
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *t)
{
#include "./ibm_editor/print_cxx_type_db.h"
} /* PrintCxxTypedb */
#endif


/*
 *  Uses the Constructor that takes no args.
 *  Assumes file f is positioned inside a class definition.
 *  All Classes get this to support the ANY type.
 */
static void
PrintCloneMethod PARAMS ((hdr, src, td),
    FILE *hdr _AND_
    FILE *src _AND_
    TypeDef *td)
{
    fprintf (hdr, "  AsnType		*Clone() const;\n\n", td->cxxTypeDefInfo->className);

    fprintf (src, "AsnType *%s::Clone() const\n", td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
    fprintf (src, "}\n\n");
} /* PrintCloneMethod */


/*
 * prints inline definition of constructors if this class is
 * derived from a library class.
 * assumes FILE *f is positioned in the derived class definition (.h)
 *
 * 12/92 MS - added overloaded "=" ops for string types.
 */
static void
PrintDerivedConstructors PARAMS ((f, r, td),
    FILE *f _AND_
    CxxRules *r _AND_
    TypeDef *td)
{
    enum BasicTypeChoiceId typeId;
    char *derivedClassName;
    char *baseClassName;

    typeId = GetBuiltinType (td->type);
    derivedClassName = td->cxxTypeDefInfo->className;
    baseClassName = td->type->cxxTypeRefInfo->className;

    /* every class gets the no-arg constructor */
#if TCL
    if (printTclG && typeId == BASICTYPE_ENUMERATED)
    {
	fprintf (f, "#if TCL\n");
	fprintf (f, "			%s(): %s (_nmdescs[0].value) {}\n", derivedClassName, baseClassName);
	fprintf (f, "#else\n");
    }
#endif /* TCL */
    fprintf (f, "			%s(): %s() {}\n", derivedClassName, baseClassName);
#if TCL
    if (printTclG && typeId == BASICTYPE_ENUMERATED)
      fprintf (f, "#endif\n");
#endif /* TCL */

    switch (typeId)
    {
        case BASICTYPE_BOOLEAN:
            fprintf (f, "			%s (bool b): %s (b) {}\n", derivedClassName, baseClassName);
            break;

        case BASICTYPE_ENUMERATED:
        case BASICTYPE_INTEGER:
            fprintf (f, "			%s (int i): %s (i) {}\n", derivedClassName, baseClassName);
            break;

        case BASICTYPE_REAL:
            fprintf (f, "			%s (double d): %s (d) {}\n", derivedClassName, baseClassName);
            break;

	case BASICTYPE_OCTETSTRING:
            fprintf (f, "			%s (const char *str): %s (str) {}\n", derivedClassName, baseClassName);

            fprintf (f, "			%s (const char *str, const size_t len): %s (str, len) {}\n", derivedClassName, baseClassName);

            fprintf (f, "			%s (const %s &o): %s (o) {}\n", derivedClassName, baseClassName, baseClassName);

            /* include overloading of = op. MS 12/92 */
            fprintf (f, "  %s		&operator = (const %s &o)	{ ReSet (o); return *this; }\n", derivedClassName, derivedClassName);
            fprintf (f, "  %s		&operator = (const char *str)	{ ReSet (str); return *this; }\n", derivedClassName);
            break;

        case BASICTYPE_BITSTRING:
            fprintf (f, "			%s (const size_t bits): %s (bits) {}\n", derivedClassName, baseClassName);

            fprintf (f, "			%s (const char *str, const size_t bitLen): %s (str, bitLen) {}\n", derivedClassName, baseClassName);

            fprintf (f, "			%s (const %s &b): %s (b) {}\n",  derivedClassName, baseClassName, baseClassName);
            break;

            /* include overloading of = op. MS 12/92 */
            fprintf (f, "  %s		&operator = (const %s &b)	{ ReSet (b); return *this; }\n", derivedClassName, derivedClassName);

        case BASICTYPE_OID:
            fprintf (f, "			%s (const char *encOid, size_t len): %s (encOid, len) {}\n", derivedClassName, baseClassName);

            fprintf (f, "			%s (const %s &o): %s (o) {}\n", derivedClassName, baseClassName, baseClassName);

            fprintf (f, "			%s (unsigned long int a1, unsigned long int a2, long int a3=-1, long int a4=-1, long int a5=-1, long int a6=-1, long int a7=-1, long int a8=-1, long int a9=-1, long int a10=-1, long int a11=-1): %s (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {}\n", baseClassName, derivedClassName, baseClassName);

            /* include overloading of = op. MS 12/92 */
            fprintf (f, "  %s		&operator = (const %s &o)	{ ReSet (o); return *this; }\n", derivedClassName, derivedClassName);

            break;


        default:
            /* do nothing */
            break;
    }

} /* PrintDerivedConstructors */


static void
PrintMakeTag PARAMS ((f, tag),
    FILE *f _AND_
    Tag *tag)
{
    char *classStr;
    char *formStr;

    classStr = Class2ClassStr (tag->tclass);

    if (tag->form == ANY_FORM)  /* default to PRIM for dual form tags */
        formStr = Form2FormStr (PRIM);
    else
        formStr = Form2FormStr (tag->form);

    fprintf (f, "MAKE_TAG_ID (%s, %s, ", classStr, formStr);
    if (tag->tclass == UNIV)
        fprintf (f, "%s)", Code2UnivCodeStr (tag->code));
    else
        fprintf (f, "%d)", tag->code);

} /* PrintMakeTag */


static void
PrintPduMemberFcns PARAMS ((src, hdr, r, cln),
    FILE *src _AND_
    FILE *hdr _AND_
    CxxRules *r _AND_
    char *cln)
{
    if (printEncodersG)
    {
        fprintf (hdr, "  int			B%s (%s b, %s &bytesEncoded);\n", r->encodePduBaseName, bufTypeNameG, lenTypeNameG);

        fprintf (src, "int %s::B%s (%s b, %s &bytesEncoded)\n", cln, r->encodePduBaseName, bufTypeNameG, lenTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "    bytesEncoded = B%s (b);\n", r->encodeBaseName);
        fprintf (src, "    return !b.WriteError();\n");
        fprintf (src, "}\n\n");
    }

    if (printDecodersG)
    {
        fprintf (hdr, "  int			B%s (%s b, %s &bytesDecoded);\n", r->decodePduBaseName, bufTypeNameG, lenTypeNameG);

        fprintf (src, "int %s::B%s (%s b, %s &bytesDecoded)\n", cln, r->decodePduBaseName, bufTypeNameG, lenTypeNameG);
	fprintf (src, "{\n");
        fprintf (src, "    %s env;\n", envTypeNameG);
        fprintf (src, "    int val;\n\n");
        fprintf (src, "    bytesDecoded = 0;\n");
        fprintf (src, "    if ((val = setjmp (env)) == 0)\n");
        fprintf (src, "    {\n");
        fprintf (src, "         BDec (b, bytesDecoded, env);\n");
        fprintf (src, "         return !b.ReadError();\n");
        fprintf (src, "    }\n");
        fprintf (src, "    else\n");
        fprintf (src, "        return false;\n");
/*
        fprintf (src, "    { std::cerr << \"longjmp return value is \" << val << std::endl;\n");
        fprintf (src, "        return false; }\n");
*/
        fprintf (src, "}\n\n");
    }

    fprintf (hdr, "\n");

} /* PrintPduMemberFcns */


static void
PrintCxxEocEncoders PARAMS ((src, td, t, bufVarName),
    FILE *src _AND_
    TypeDef *td _AND_
    Type *t _AND_
    char *bufVarName)
{
    TagList *tl;
    Tag *tag;
    int stoleChoiceTags;

    /*
     * get all the tags on this type
     */
    tl = (TagList*) GetTags (t, &stoleChoiceTags);

    /*
     * leave choice elmt tag enc to encoding routine
     */
    if (!stoleChoiceTags)
    {
        FOR_EACH_LIST_ELMT (tag, tl)
            if (tag->form == CONS)
                fprintf (src, "      BEncEocIfNec (b);\n");
    }

    FreeTags (tl);

} /* PrintCxxEocEncoders */


static int
HasShortLen PARAMS ((t),
    Type *t)
{
    enum BasicTypeChoiceId typesType;
    /*
     * efficiency hack - use simple length (1 byte)
     * encoded for type (almost) guaranteed to have
     * encoded lengths of 0 <= len <= 127
     */
    typesType = GetBuiltinType (t);
    return typesType == BASICTYPE_BOOLEAN || typesType == BASICTYPE_INTEGER || typesType == BASICTYPE_NULL || typesType == BASICTYPE_REAL || typesType == BASICTYPE_ENUMERATED;
} /* HasShortLen */


/*
 * prints length encoding code.  Primitives always use
 * definite length and constructors get "ConsLen"
 * which can be configured at compile to to be indefinite
 * or definite.  Primitives can also be "short" (isShort is true)
 * in which case a fast macro is used to write the length.
 * Types for which isShort apply are: boolean, null and
 * (almost always) integer and reals
 */
static void
PrintCxxLenEncodingCode PARAMS ((f, isCons, isShort, lenVarName, bufVarName),
    FILE *f _AND_
    int isCons _AND_
    int isShort _AND_
    char *lenVarName _AND_
    char *bufVarName)
{
    if (isCons)
        fprintf (f, "    %s += BEncConsLen (%s, %s);\n", lenVarName, bufVarName, lenVarName);
    else
    {
        if (isShort)
        {
            fprintf (f, "    BEncDefLenTo127 (%s, %s);\n", bufVarName, lenVarName);
            fprintf (f, "    %s++;\n", lenVarName);
        }
        else
            fprintf (f, "    %s += BEncDefLen (%s, %s);\n", lenVarName, bufVarName, lenVarName);
    }
} /* PrintCxxLenEncodingCode */


/*
 * prints last tag's encoding code first
 */
static void
PrintCxxTagAndLenList PARAMS ((src, t, tagList, lenVarName, bufVarName),
    FILE *src _AND_
    Type *t _AND_
    TagList *tagList _AND_
    char *lenVarName _AND_
    char *bufVarName)
{
    char *classStr;
    char *formStr;
    char *codeStr;
    Tag *tg;
    Tag *last;
    int tagLen;
    enum BasicTypeChoiceId typesType;
    int isShort;

    if ((tagList == NULL) || LIST_EMPTY (tagList))
        return;

    /*
     * efficiency hack - use simple length (1 byte)
     * encoded for type (almost) guaranteed to have
     * encoded lengths of 0 <= len <= 127
     */
    isShort = HasShortLen (t);

    /*
     * since encoding backward encode tags backwards
     */
    last = (Tag*)LAST_LIST_ELMT (tagList);
    FOR_EACH_LIST_ELMT_RVS (tg, tagList)
    {
        classStr = Class2ClassStr (tg->tclass);

        if (tg->form == CONS)
        {
            formStr = Form2FormStr (CONS);
            PrintCxxLenEncodingCode (src, TRUE, isShort, lenVarName, bufVarName);
        }
        else /* PRIM or ANY_FORM */
        {
            formStr = Form2FormStr (PRIM);
            PrintCxxLenEncodingCode (src, FALSE, isShort, lenVarName, bufVarName);
        }

/*      GetTags sets the form properly now
        if (IsPrimitiveByDefOrRef (t) && (tg == last))
        {
            formStr = Form2FormStr (PRIM);
            PrintCxxLenEncodingCode (src, FALSE, isShort, lenVarName, bufVarName);
        }
        else
        {
            formStr = Form2FormStr (CONS);
            PrintCxxLenEncodingCode (src, TRUE, isShort, lenVarName, bufVarName);
        }
*/

        fprintf (src, "\n");

        tagLen = TagByteLen (tg->code);

        if (tg->tclass == UNIV)
            fprintf (src, "    %s += BEncTag%d (%s, %s, %s, %s);\n", lenVarName, tagLen, bufVarName, classStr, formStr, Code2UnivCodeStr (tg->code));
        else
            fprintf (src, "    %s += BEncTag%d (%s, %s, %s, %d);\n", lenVarName, tagLen, bufVarName, classStr, formStr, tg->code);
    }

} /* PrintCxxTagAndLenList */


/*
 *  Recursively walks through tags, printing lower lvl tags
 *  first (since encoding is done backwards).
 *
 */
static void
PrintCxxTagAndLenEncodingCode PARAMS ((src, td, t, lenVarName, bufVarName),
    FILE *src _AND_
    TypeDef *td _AND_
    Type *t _AND_
    char *lenVarName _AND_
    char *bufVarName)
{
    TagList *tl;
    int stoleChoiceTags;

    /*
     * get all the tags on this type
     */
    tl = (TagList*) GetTags (t, &stoleChoiceTags);

    /*
     * leave choice elmt tag enc to encoding routine
     */
    if (!stoleChoiceTags)
        PrintCxxTagAndLenList (src, t, tl, lenVarName, bufVarName);

    FreeTags (tl);

} /* PrintCxxTagAndLenEncodingCode */


/*
 * used to figure out local variables to declare
 * for decoding tags/len pairs on type t
 */
static int
CxxCountVariableLevels PARAMS ((t),
    Type *t)
{
    if (GetBuiltinType (t) == BASICTYPE_CHOICE)
        return CountTags (t) +1; /* since must decode 1 internal tag type */
    else
        return CountTags (t);
} /* CxxCountVariableLevels */


/*
 * returns true if elmts curr following
 *  onward are all optional ow. false
 */
static int
RestAreTailOptional PARAMS ((e),
    NamedTypeList *e)
{
    NamedType *elmt;
    void *tmp;
    int retVal;

    if (e == NULL)
        return TRUE;

    tmp = (void*)CURR_LIST_NODE (e);
    retVal = TRUE;
    AsnListNext (e);
    FOR_REST_LIST_ELMT (elmt, e)
    {
        if ((!elmt->type->optional) && (elmt->type->defaultVal == NULL))
        {
            retVal = FALSE;
            break;
        }
    }
    SET_CURR_LIST_NODE (e, tmp); /* reset list to orig loc */
    return retVal;
}


/*
 * prints typedef or new class given an ASN.1  type def of a primitive type
 * or typeref.  Uses inheritance to cover re-tagging and named elmts.
 */
static void
PrintCxxSimpleDef PARAMS ((hdr, src, if_IBM_ENC (hdrdb COMMA srcdb COMMA) if_META (m COMMA) r, td),
    FILE *hdr _AND_
    FILE *src _AND_
    if_IBM_ENC (FILE *hdrdb _AND_)
    if_IBM_ENC (FILE *srcdb _AND_)
    if_META (Module *m _AND_)
    CxxRules *r _AND_
    TypeDef *td)
{
    Tag *tag;
    TagList *tags;
    char *formStr;
    char *classStr;
    int tagLen;
    int i;
    CNamedElmt *n;
    int stoleChoiceTags;
    int elmtLevel;
    enum BasicTypeChoiceId typeId;

    fprintf (hdr, "/* ");
    SpecialPrintType (hdr, td, td->type);
    fprintf (hdr, " */\n");

    /* check if has been re-tagged
     *   eg Foo ::= [APPLICATION 2] IMPLICIT REAL
     * or if it has named elmts in which case a new class must
     * be defined
     *  eg Foo ::= INTEGER { one (1), two (2), three (3) }
     */

    if (IsNewType (td->type))
    {
	int	hasNamedElmts;

#ifdef _IBM_ENC_
#include "./ibm_editor/print_cxx_simple_def.h"
#endif /* _IBM_ENC_ */

        fprintf (hdr, "class %s: public %s\n", td->cxxTypeDefInfo->className, td->type->cxxTypeRefInfo->className);
        fprintf (hdr, "{\n");
        fprintf (hdr, "public:\n");

        /*
         * must explicitly call constructors for base class
         */
        PrintDerivedConstructors (hdr, r, td);

        /* do named elmts enum if any */
        /* for types with named elements, inherit from the base
         * class and define and enum eg:
         * Foo ::= INTEGER { one (1), two (2), five (5) }
         *  ->
         * class Foo: public AsnInt
         * {
         * public:
         *		Foo(): AsnInt() {}
         *		Foo (int val): AsnInt (int val) {}
         *    enum { one = 1, two = 2, five = 5 };
         * };
         * or
         * Foo2 ::= [APPLICATION 2] INTEGER
         * -->
         * class Foo: public AsnInt
         * {
         * public:
         *		Foo(): AsnInt() {}
         *		Foo (int val): AsnInt (int val) {}
         *     AsnLen	BEnc { ....... } <-- holds new tag enc/dec
         *     void	BDec { ....... }   <--/
         *     int	BEncPdu { ....... }
         *     int	BDecPdu { ....... }
         * };
         * (must 'inherit' constructors explicitly)
         */

        if (hasNamedElmts = HasNamedElmts (td->type))
        {
            fprintf (hdr, "  enum\n");
            fprintf (hdr, "  {\n");
            FOR_EACH_LIST_ELMT (n, td->type->cxxTypeRefInfo->namedElmts)
            {
                fprintf (hdr, "    %s = %d", n->name, n->value);
                if (n != (CNamedElmt *)LAST_LIST_ELMT (td->type->cxxTypeRefInfo->namedElmts))
                    fprintf (hdr, ",\n");
                else
                    fprintf (hdr, "\n");
            }
            fprintf (hdr, "  };\n");
        }
#if META
	if (printMetaG)
	{
	    const char	*T, *t;
	    int a3;

	    fprintf (hdr, "\n");
	    fprintf (hdr, "#if META\n");
	    fprintf (src, "#if META\n\n");

	    fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "}\n\n");

	    if (hasNamedElmts = HasNamedElmts (td->type))
	    {
		fprintf (hdr, "  static const AsnNameDesc	_nmdescs[];\n");

		fprintf (src, "const AsnNameDesc %s::_nmdescs[] =\n", td->cxxTypeDefInfo->className);
		fprintf (src, "{\n");
		FOR_EACH_LIST_ELMT (n, td->type->cxxTypeRefInfo->namedElmts)
#if 0 /* (no asn1 names available!) */
		    if (printMetaG == META_backend_names)
		    else /* META_asn1_names */
#endif
			fprintf (src, "  \"%s\", %s, // %d\n", n->name, n->name, n->value);
		fprintf (src, "  NULL, -1\n");
		fprintf (src, "};\n\n");
	    }

	    switch (GetBuiltinType (td->type))
	    {
		case BASICTYPE_BOOLEAN:
		    T = "BOOLEAN";
		    t = "Bool";
		    a3 = FALSE;
		    break;
		case BASICTYPE_ENUMERATED:
		    T = "ENUMERATED";
		    t = "Enum";
		    a3 = TRUE;
		    break;
		case BASICTYPE_INTEGER:
		    T = "INTEGER";
		    t = "Int";
		    a3 = TRUE;
		    break;
		case BASICTYPE_REAL:
		    T = "REAL";
		    t = "Real";
		    a3 = FALSE;
		    break;
		case BASICTYPE_OCTETSTRING:
		    T = "OCTET_STRING";
		    t = "Octs";
		    a3 = FALSE;
		    break;
		case BASICTYPE_BITSTRING:
		    T = "BIT_STRING";
		    t = "Bits";
		    a3 = TRUE;
		    break;
		case BASICTYPE_OID:
		    T = "OID";
		    t = "Oid";
		    a3 = FALSE;
	    	default:
		    T =
		    t = "?";
		    a3 = FALSE;
	    }

	    fprintf (hdr, "  static const Asn%sTypeDesc	_desc;\n", t);
	    fprintf (hdr, "  const AsnTypeDesc	*_getdesc() const;\n");

	    fprintf (src, "const Asn%sTypeDesc %s::_desc\n", t, td->cxxTypeDefInfo->className);
	    fprintf (src, "(\n");
	    fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	    if (printMetaG == META_backend_names)
		fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	    else /* META_asn1_names */
		fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	    fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	    fprintf (src, "  AsnTypeDesc::%s,\n", T);
	    fprintf (src, "  create%s", td->cxxTypeDefInfo->className);
	    if (a3)
		fprintf (src, ",\n  %s", hasNamedElmts ? "_nmdescs" : "NULL");
	    fprintf (src, "\n);\n\n");

	    fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  return &_desc;\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "#endif // META\n");
	    fprintf (src, "#endif // META\n\n");

#if TCL
#endif
	}
#endif /* META */

        /*
         * Re-do BerEncode, BerDeocode, BerDecodePdu and BerDecodePdu
         * if this type has been re-tagged
         */
        if ((IsDefinedByLibraryType (td->type) && !HasDefaultTag (td->type))
	  || (IsTypeRef (td->type) && ((td->type->tags != NULL) && !LIST_EMPTY (td->type->tags))))
        {
            /* only BerEn/Decode BerEn/DecodePdu need to be re-done if tags are different */

            /* print clone routine for ANY mgmt */
            PrintCloneMethod (hdr, src, td);

            tags = GetTags (td->type, &stoleChoiceTags);
            typeId = GetBuiltinType (td->type);

            /* do BerEncode function */
            if (printEncodersG)
            {
                fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);
                fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName, bufTypeNameG);
                fprintf (src, "{\n");
                fprintf (src, "    %s l;\n", lenTypeNameG);

                PrintCxxEocEncoders (src, td, td->type, "b");

                fprintf (src, "    l = BEncContent (b);\n");

                /* encode each tag/len pair if any */
                if (!stoleChoiceTags)
                {
                    FOR_EACH_LIST_ELMT_RVS (tag, tags)
                    {
                        classStr = Class2ClassStr (tag->tclass);

                        if (tag->form == ANY_FORM)
                        {
                            formStr = Form2FormStr (PRIM);
                            PrintCxxLenEncodingCode (src, FALSE, HasShortLen (td->type), "l", "b");
                        }
                        else
                        {
                            formStr = Form2FormStr (tag->form);
                            PrintCxxLenEncodingCode (src, TRUE, HasShortLen (td->type), "l", "b");
                        }

                        fprintf (src, "\n");
                        tagLen = TagByteLen (tag->code);

                        if (tag->tclass == UNIV)
                            fprintf (src, "    l += BEncTag%d (b, %s, %s, %s);\n", tagLen, classStr, formStr, Code2UnivCodeStr (tag->code));
                        else
                            fprintf (src, "    l += BEncTag%d (b, %s, %s, %d);\n", tagLen, classStr, formStr, tag->code);
                    }
                }
                fprintf (src, "    return l;\n");
                fprintf (src, "}\n\n");
            }
            /* end of BEnc function */

            /* Do BDec function */
            if (printDecodersG)
            {
                fprintf (hdr, "  void			B%s (%s b, %s &bytesDecoded, %s env);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);
                fprintf (src, "void %s::B%s (%s b, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);
                fprintf (src, "{\n");
                fprintf (src, "    %s tag;\n", tagTypeNameG);

                /* print extra locals for redundant lengths */
                for (i = 1; (tags != NULL) && (i <= LIST_COUNT (tags)); i++)
                    fprintf (src, "    %s elmtLen%d;\n", lenTypeNameG, i);
                if (typeId == BASICTYPE_CHOICE)
                    fprintf (src, "    %s elmtLen%d;\n", lenTypeNameG, i++);
                fprintf (src, "\n");

                /*  decode tag/length pair (s) */
                elmtLevel = 0;
                if (!stoleChoiceTags)
                {
                    FOR_EACH_LIST_ELMT (tag, tags)
                    {
                        classStr = Class2ClassStr (tag->tclass);

                        if (tag->form == ANY_FORM)
                            formStr = Form2FormStr (PRIM);
                        else
                            formStr = Form2FormStr (tag->form);

                        fprintf (src, "    if (((tag = BDecTag (b, bytesDecoded, env)) != ");

                        if (tag->tclass == UNIV)
                        {
                            fprintf (src, "MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, Code2UnivCodeStr (tag->code));
                            if (tag->form == ANY_FORM)
                                fprintf (src, "\n        && (tag != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), Code2UnivCodeStr (tag->code));
                            else
                                fprintf (src, ")\n");
                        }
                        else
                        {
                            fprintf (src, "MAKE_TAG_ID (%s, %s, %d))", classStr, formStr, tag->code);
                            if (tag->form == ANY_FORM)
                                fprintf (src, "\n        && (tag != MAKE_TAG_ID (%s, %s, %d)))\n", classStr, Form2FormStr (CONS), tag->code);
                            else
                                fprintf (src, ")\n");
                        }
                        fprintf (src, "    {\n");
            		fprintf (src, "        Asn1Error << \"%s::B%s: ERROR - wrong tag\" << std::endl;\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
                        fprintf (src, "        longjmp (env, %d);\n", longJmpValG--);
                        fprintf (src, "    }\n");

                        fprintf (src, "    elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
                    }
                }

                /* decode first tag from CHOICE's content */
                if (typeId == BASICTYPE_CHOICE)
                {
                    fprintf (src, "    tag = BDecTag (b, bytesDecoded, env);\n");
                    fprintf (src, "    elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
                }

                fprintf (src, "    B%s (b, tag, elmtLen%d, bytesDecoded, env);\n", r->decodeContentBaseName, i-1);

                /* grab any EOCs that match redundant, indef lengths */
                for (i = elmtLevel-1; i > 0; i--)
                {
                    fprintf (src, "    if (elmtLen%d == INDEFINITE_LEN)\n", i);
                    fprintf (src, "        BDecEoc (b, bytesDecoded, env);\n");
                }

                fprintf (src, "}\n\n");
            }
            /* end of BDec function */

            PrintPduMemberFcns (src, hdr, r, td->cxxTypeDefInfo->className);

            FreeTags (tags);
        }
        /* close class def */
        fprintf (hdr, "};\n\n\n");

    }
    else  /* isomorphic with referenced type, so just to a typedef */
    {
#ifdef _IBM_ENC_
#include "./ibm_editor/print_cxx_simple_def1.h"
#endif /* _IBM_ENC_ */

#if META
	if (printMetaG)
	{
	    fprintf (hdr, "#if META\n");
	    fprintf (src, "#if META\n\n");

	    fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "struct %s: public %s\n", td->cxxTypeDefInfo->className, td->type->cxxTypeRefInfo->className);
	    fprintf (hdr, "{\n");

	    PrintDerivedConstructors (hdr, r, td);

            PrintCloneMethod (hdr, src, td);

	    fprintf (hdr, "  static const AsnAliasTypeDesc	_desc;\n");
	    fprintf (hdr, "  const AsnTypeDesc	*_getdesc() const;\n");

	    fprintf (src, "const AsnAliasTypeDesc %s::_desc\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "(\n");
	    fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	    if (printMetaG == META_backend_names)
		fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	    else /* META_asn1_names */
		fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	    fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	    fprintf (src, "  AsnTypeDesc::ALIAS,\n");
	    fprintf (src, "  create%s,\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "  &%s::_desc\n);\n\n", td->type->cxxTypeRefInfo->className);

	    fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  return &_desc;\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "};\n\n");

	    fprintf (hdr, "#else // META\n\n");
	    fprintf (src, "#endif // META\n\n");
	}
#endif /* META */

        fprintf (hdr, "typedef %s %s;\n\n", td->type->cxxTypeRefInfo->className, td->cxxTypeDefInfo->className);

#if META
	if (printMetaG)
	    fprintf (hdr, "#endif // META\n\n");
#endif /* META */
    }
} /* PrintCxxSimpleDef */

static void
PrintCxxChoiceDefCode PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, parent, choice, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *choice _AND_
    int novolatilefuncs)
{
    NamedType *e;
    char *classStr;
    char *formStr;
    char *codeStr;
    int tagLen, i;
    Tag *tag;
    TagList *tags;
    char *varName;
    CxxTRI *cxxtri;
    int elmtLevel;
    int varCount, tmpVarCount;
    int stoleChoiceTags;
    enum BasicTypeChoiceId tmpTypeId;
    NamedType *defByNamedType;

#ifdef _IBM_ENC_
#include "./ibm_editor/print_cxx_choice_def_code.h"
#endif /* _IBM_ENC_ */

    /* put class spec in hdr file */

    fprintf (hdr, "class %s%s\n", td->cxxTypeDefInfo->className, baseClassesG);
    fprintf (hdr, "{\n");
    fprintf (hdr, "public:\n");

    /* write out choiceId enum type */

    fprintf (hdr, "  enum %s\n", r->choiceIdEnumName);
    fprintf (hdr, "  {\n");
    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
    {
        fprintf (hdr, "     %s = %d", e->type->cxxTypeRefInfo->choiceIdSymbol, e->type->cxxTypeRefInfo->choiceIdValue);
        if (e != (NamedType*)LAST_LIST_ELMT (choice->basicType->a.choice))
            fprintf (hdr, ",\n");
        else
            fprintf (hdr, "\n");
    }
    fprintf (hdr, "  };\n\n");

    /* write out the choice Id field */
    /*     fprintf (hdr, "protected:\n"); */
    fprintf (hdr, "  enum %s	%s;\n", r->choiceIdEnumName, r->choiceIdFieldName);

    /* write out the choice element anonymous union */
    fprintf (hdr, "  union\n");
    fprintf (hdr, "  {\n");
    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
    {
        fprintf (hdr, "     ");
        PrintCxxType (hdr, mods, m, r, td, choice, e->type);
        fprintf (hdr, "%s;\n", e->type->cxxTypeRefInfo->fieldName);
    }
    fprintf (hdr, "  };\n\n");

#if META
    if (printMetaG)
    {
	fprintf (hdr, "#if META\n");
	fprintf (src, "#if META\n\n");

	fprintf (hdr, "  static const AsnChoiceTypeDesc	_desc;\n");
	fprintf (hdr, "  static const AsnChoiceMemberDesc	_mdescs[];\n\n");
	fprintf (hdr, "  const AsnTypeDesc		*_getdesc() const;\n");
	fprintf (hdr, "  AsnType			*_getref (const char *membername, bool create = false);\n\n");

	fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	fprintf (src, "}\n\n");

	fprintf (src, "const AsnChoiceMemberDesc %s::_mdescs[] =\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
	    if (printMetaG == META_backend_names)
		fprintf (src, "  AsnChoiceMemberDesc (\"%s\", &%s::_desc), // `%s'\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->fieldName ? e->fieldName : "");
	    else /* META_asn1_names */
		fprintf (src, "  AsnChoiceMemberDesc (\"%s\", &%s::_desc), // `%s'\n", e->fieldName ? e->fieldName : e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "  AsnChoiceMemberDesc()\n");
	fprintf (src, "};\n\n");

	fprintf (src, "const AsnChoiceTypeDesc %s::_desc\n", td->cxxTypeDefInfo->className);
	fprintf (src, "(\n");
	fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	if (printMetaG == META_backend_names)
	    fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	else /* META_asn1_names */
	    fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	fprintf (src, "  AsnTypeDesc::CHOICE,\n");
	fprintf (src, "  create%s,\n", td->cxxTypeDefInfo->className);
	fprintf (src, "  _mdescs\n");
	fprintf (src, ");\n\n");

	fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return &_desc;\n");
	fprintf (src, "}\n\n");

	fprintf (src, "AsnType *%s::_getref (const char *membername, bool create)\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  ChoiceIdEnum newCid = (ChoiceIdEnum)_desc.choicebyname (membername);\n");
	fprintf (src, "  if (newCid == -1)\n");
	fprintf (src, "    return NULL;\n");
	fprintf (src, "  if (newCid == choiceId)\n");
	fprintf (src, "  {\n");
	fprintf (src, "    switch (choiceId)\n");
	fprintf (src, "    {\n");
	FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
	{
	    fprintf (src, "      case %sCid:\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "        return %s;\n", e->type->cxxTypeRefInfo->fieldName);
	}
	fprintf (src, "      default:\n");
	fprintf (src, "        return NULL;\n");
	fprintf (src, "    }\n");
	fprintf (src, "  }\n");
	fprintf (src, "  else\n");
	fprintf (src, "  {\n");
	fprintf (src, "    if (create)\n");
	fprintf (src, "    {\n");
	fprintf (src, "//      switch (choiceId)\n");
	fprintf (src, "//      {\n");
	FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
	{
	    fprintf (src, "//        case %sCid:\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "//          delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "//          %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "//          break;\n");
	}
	fprintf (src, "//        default:\n");
	fprintf (src, "//          return NULL;\n");
	fprintf (src, "//      }\n");
	e = FIRST_LIST_ELMT (choice->basicType->a.choice);
	fprintf (src, "      // simply delete any member, the virtual function table takes care of the rest:\n");
	fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "      switch (choiceId = newCid)\n");
	fprintf (src, "      {\n");
	FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
	{
	    fprintf (src, "        case %sCid:\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "          return %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
	}
	fprintf (src, "        default: // internal error!\n");
	fprintf (src, "          return NULL;\n");
	fprintf (src, "      }\n");
	fprintf (src, "    }\n");
	fprintf (src, "    else\n");
	fprintf (src, "      return NULL;\n");
	fprintf (src, "  }\n");
	fprintf (src, "}\n\n");

#if TCL
	if (printTclG)
	{
	    fprintf (hdr, "#if TCL\n");
	    fprintf (src, "#if TCL\n\n");

	    fprintf (hdr, "  int			TclGetDesc (Tcl_DString *) const;\n");
	    fprintf (hdr, "  int			TclGetVal (Tcl_Interp *) const;\n");
	    fprintf (hdr, "  int			TclSetVal (Tcl_Interp *, const char *valstr);\n\n");

	    fprintf (src, "int %s::TclGetDesc (Tcl_DString *valstr) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DStringAppendElement (valstr, (char*)_desc.choicebyvalue (choiceId));\n");
	    fprintf (src, "  // hack: since all members are pointers, we don't have to check for its type via choiceId, because all we want to know is whether it's NULL or not:\n");
	    e = FIRST_LIST_ELMT (choice->basicType->a.choice);
	    fprintf (src, "  Tcl_DStringAppendElement (valstr, %s ? \"valid\" : \"void\");\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclGetVal (Tcl_Interp *interp) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  switch (choiceId)\n");
	    fprintf (src, "  {\n");
	    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
	    {
		fprintf (src, "    case %sCid:\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "      if (%s)\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "        if (%s->TclGetVal (interp) != TCL_OK)\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "          return TCL_ERROR;\n");
		fprintf (src, "      break;\n");
	    }
	    fprintf (src, "    default:\n");
	    fprintf (src, "      Tcl_SetResult (interp, \"illegal choiceId in %s\", TCL_STATIC);\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "      Tcl_SetErrorCode (interp, \"SNACC\", \"ILLCHOICE\", NULL);\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  Tcl_DString valstr;\n");
	    fprintf (src, "  Tcl_DStringInit (&valstr);\n");
	    fprintf (src, "  Tcl_DStringAppendElement (&valstr, (char*)_desc.choicebyvalue (choiceId));\n");
	    fprintf (src, "  Tcl_DStringAppendElement (&valstr, interp->result);\n");
	    fprintf (src, "  Tcl_ResetResult (interp);\n");
	    fprintf (src, "  Tcl_DStringResult (interp, &valstr);\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclSetVal (Tcl_Interp *interp, const char *valstr)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Args elem;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)valstr, &elem.c, &elem.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  if (elem.c != 2)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    sprintf (interp->result, \"syntax error: expected a pair, but it's got %%d element(s)\", elem.c);\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  AsnType *member = _getref (elem.v[0], true);\n");
	    fprintf (src, "  if (!member)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    Tcl_AppendResult (interp, \"illegal choice \", elem.v[0], \" for %s\", NULL);\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "    Tcl_SetErrorCode (interp, \"SNACC\", \"ILLCHOICE\", NULL);\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  return member->TclSetVal (interp, elem.v[1]);\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "#endif // TCL\n");
	    fprintf (src, "#endif // TCL\n\n");
	}
#endif /* TCL */

	fprintf (hdr, "#endif // META\n");
	fprintf (src, "#endif // META\n\n");
    }
#endif /* META */

    fprintf (hdr, "\n");

    /* constructors and destructor */

    fprintf (hdr, "			%s();\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    e = FIRST_LIST_ELMT (choice->basicType->a.choice);
    fprintf (src, "  choiceId = %sCid;\n", e->type->cxxTypeRefInfo->fieldName);
    fprintf (src, "#if TCL\n");
    fprintf (src, "  %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
    fprintf (src, "#else\n");
    fprintf (src, "  %s = NULL; // incomplete initialization of mandatory element!\n", e->type->cxxTypeRefInfo->fieldName);
    fprintf (src, "#endif // TCL\n");
    fprintf (src, "}\n\n");

    fprintf (hdr, "			%s (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s::%s (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "}\n\n");

    fprintf (hdr, "			~%s();\n\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::~%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  switch (choiceId)\n");
    fprintf (src, "  {\n");
    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
    {
	fprintf (src, "    case %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);
	if (e->type->cxxTypeRefInfo->isPtr)
	    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "      break;\n");
    }
    fprintf (src, "  } // end of switch\n");
    fprintf (src, "} // end of destructor\n");
    fprintf (src, "\n");

    /* print clone routine for ANY mgmt */
    PrintCloneMethod (hdr, src, td);

    fprintf (hdr, "  %s		&operator = (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &that)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "{\n");
    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "  if (this != &that)\n");
    fprintf (src, "  {\n");
    fprintf (src, "    switch (choiceId)\n");
    fprintf (src, "    {\n");
    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
    {
	if (e->type->cxxTypeRefInfo->isPtr)
	{
	    fprintf (src, "      case %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);
	    fprintf (src, "        delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "        break;\n");
	}
    }
    fprintf (src, "    }\n");
    fprintf (src, "    switch (choiceId = that.choiceId)\n");
    fprintf (src, "    {\n");
    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
    {
	fprintf (src, "      case %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);
	if (e->type->cxxTypeRefInfo->isPtr)
	{
	    fprintf (src, "        %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
	    fprintf (src, "        *%s = *that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
	}
	else
	    fprintf (src, "        %s = that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "        break;\n");
    }
    fprintf (src, "    }\n");
    fprintf (src, "  }\n");
    fprintf (src, "\n");
    fprintf (src, "  return *this;\n");
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s &%s::operator = (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "  // if your compiler complains here, check the -novolat option\n");
    if (novolatilefuncs)
    {
      fprintf (src, "  return *this;\n");
    }
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "}\n\n");

    /* BerEncodeContent */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeContentBaseName, bufTypeNameG);

        fprintf (src, "%s\n", lenTypeNameG);
        fprintf (src, "%s::B%s (%s b)\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName, bufTypeNameG);
        fprintf (src, "{\n");

        /* print local vars */
        fprintf (src, "  %s l;\n", lenTypeNameG);

        fprintf (src, "  switch (%s)\n", r->choiceIdFieldName);
        fprintf (src, "  {\n");
        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
        {
            cxxtri =  e->type->cxxTypeRefInfo;
            fprintf (src, "    case %s:\n", cxxtri->choiceIdSymbol);

            varName = cxxtri->fieldName;

            /* encode Eoc (s) if nec */
            PrintCxxEocEncoders (src, td, e->type, "b");

            /* encode content */
            tmpTypeId = GetBuiltinType (e->type);
            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
            {
                fprintf (src, "        %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                {
                    fprintf (src, "SetTypeByOid (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }
                else
                {
                    fprintf (src, "SetTypeByInt (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }

                fprintf (src, "      l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else if (tmpTypeId == BASICTYPE_ANY)
            {
                fprintf (src, "        %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "SetTypeBy???(???);\n");

                fprintf (src, "      l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else
            {
                fprintf (src, "      l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                fprintf (src, "B%s (b);\n", r->encodeContentBaseName);
            }


            /* encode tag (s) & len (s) */
            PrintCxxTagAndLenEncodingCode (src, td, e->type, "l", "b");


            fprintf (src, "      break;\n\n");
        }
        fprintf (src, "  } // end switch\n");

        fprintf (src, "  return l;\n");
        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName);
    }
    /* end of BerEncodeContent method */

    /* BerDecodeContent */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s tag, %s elmtLen, %s &bytesDecoded, %s env);\n", r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s tag, %s elmtLen0, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "{\n");

        /* print local vars */
        /* count max number of extra length var nec
         * by counting tag/len pairs on components of the CHOICE
         */
        varCount = 0;
        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
        {
            tmpVarCount = CxxCountVariableLevels (e->type);
            if (tmpVarCount > varCount)
                varCount = tmpVarCount;
        }
        /* write extra length vars - remeber choice content
         * decoders are passed the 'key' tag so need one less
         * than max var count.
         */
        for (i = 1; i < varCount; i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);

        /* switch on given tag - choices always have the key tag decoded */
        fprintf (src, "  switch (tag)\n");
        fprintf (src, "  {\n");
        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
        {
            cxxtri =  e->type->cxxTypeRefInfo;

            tags = GetTags (e->type, &stoleChoiceTags);

            if (LIST_EMPTY (tags))
            {
                fprintf (src, "    // ANY Type?\n");
                fprintf (src, "    case MAKE_TAG_ID (?, ?, ?):\n");
            }
            else
            {
                tag = (Tag*)FIRST_LIST_ELMT (tags);
                classStr = Class2ClassStr (tag->tclass);
                codeStr = Code2UnivCodeStr (tag->code);
                formStr = Form2FormStr (tag->form);

                if (tag->tclass == UNIV)
                {
                    if (tag->form == ANY_FORM)
                    {
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
                    }
                    else
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
                }
                else
                {
                    if (tag->form == ANY_FORM)
                    {
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (PRIM), tag->code);
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (CONS), tag->code);
                    }
                    else
                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, formStr, tag->code);
                }

                /* now decode extra tags/length pairs */
                AsnListFirst (tags);
                AsnListNext (tags);
                elmtLevel = 0;
                if (stoleChoiceTags)
                {
                    FOR_REST_LIST_ELMT (tag, tags)
                    {
                        classStr = Class2ClassStr (tag->tclass);
                        codeStr = Code2UnivCodeStr (tag->code);
                        formStr = Form2FormStr (tag->form);

                        if (tag->tclass == UNIV)
                        {
                            if (tag->form == ANY_FORM)
                            {
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
                            }
                            else
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
                        }
                        else
                        {
                            if (tag->form == ANY_FORM)
                            {
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (PRIM), tag->code);
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (CONS), tag->code);
                            }
                            else
                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %d):\n", classStr, formStr, tag->code);
                        }
                    }
                }
                else /* didn't steal nested choice's tags */
                {
                    FOR_REST_LIST_ELMT (tag, tags)
                    {
                        classStr = Class2ClassStr (tag->tclass);
                        codeStr = Code2UnivCodeStr (tag->code);
                        formStr = Form2FormStr (tag->form);

                        fprintf (src, "      tag = BDecTag (b, bytesDecoded, env);\n");
                        if (tag->form == ANY_FORM)
                        {
                            if (tag->tclass == UNIV)
                            {
                                fprintf (src, "      if ((tag != MAKE_TAG_ID (%s, %s, %s))\n",  classStr, Form2FormStr (PRIM), codeStr);
                                fprintf (src, "          && (tag != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), codeStr);
                            }
                            else
                            {
                                fprintf (src, "      if ((tag != MAKE_TAG_ID (%s, %s, %d))\n", classStr, Form2FormStr (PRIM), tag->code);
                                fprintf (src, "          && (tag != MAKE_TAG_ID (%s, %s, %d)))\n", classStr, Form2FormStr (CONS), tag->code);
                            }

                        }
                        else
                        {
                            if (tag->tclass == UNIV)
                                fprintf (src, "      if (tag != MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, codeStr);
                            else
                                fprintf (src, "      if (tag != MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
                        }

                        fprintf (src, "      {\n");
                        fprintf (src, "         Asn1Error << \"Unexpected Tag\" << std::endl;\n");
                        fprintf (src, "         longjmp (env, %d);\n", longJmpValG--);
                        fprintf (src, "      }\n\n");

                        fprintf (src, "      elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
                    }
                }
            }
            /*
             * if the choices element is another choice &&
             * we didn't steal its tags then we must grab
             * the key tag out of the contained CHOICE
             */
            if (!stoleChoiceTags && (GetBuiltinType (e->type) == BASICTYPE_CHOICE))
            {
                fprintf (src, "      tag = BDecTag (b, bytesDecoded, env);\n");
                fprintf (src, "      elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
            }

            varName = cxxtri->fieldName;

            /* set choice id for to this elment */
            fprintf (src, "      %s = %s;\n", r->choiceIdFieldName, cxxtri->choiceIdSymbol);

            /* alloc elmt if nec */
            if (cxxtri->isPtr)
                fprintf (src, "      %s = new %s;\n", varName, cxxtri->className);

            /* decode content */
            tmpTypeId = GetBuiltinType (e->type);
            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
            {
                /*
                 * must check for another EOC for ANYs
                 * since the any decode routines decode
                 * their own first tag/len pair
                 */
                elmtLevel++;

                fprintf (src, "      %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                {
                    fprintf (src, "SetTypeByOid (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }
                else
                {
                    fprintf (src, "SetTypeByInt (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }

                fprintf (src, "      %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b, bytesDecoded, env);\n",  r->decodeBaseName);
            }
            else if (tmpTypeId == BASICTYPE_ANY)
            {
                /*
                 * must check for another EOC for ANYs
                 * since the any decode routines decode
                 * their own first tag/len pair
                 */
                elmtLevel++;

                fprintf (src, "      %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "SetTypeBy???(???);\n");

                fprintf (src, "      %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b, bytesDecoded, env);\n",  r->decodeBaseName);
            }
            else
            {
                fprintf (src, "        %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                fprintf (src, "B%s (b, tag, elmtLen%d, bytesDecoded, env);\n",  r->decodeContentBaseName, elmtLevel);
            }

            /* decode Eoc (s) */
            for (i = elmtLevel-1; i >= 0; i--)
            {
                fprintf (src, "      if (elmtLen%d == INDEFINITE_LEN)\n", i);
                fprintf (src, "        BDecEoc (b, bytesDecoded, env);\n");
            }

            fprintf (src, "      break;\n\n");
            FreeTags (tags);
        }

        fprintf (src, "    default:\n");
        fprintf (src, "      Asn1Error << \"ERROR - unexpected tag in CHOICE\" << std::endl;\n");
        fprintf (src, "      longjmp (env, %d);\n", longJmpValG--);
        fprintf (src, "      break;\n");

        fprintf (src, "  } // end switch\n");
        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName);
    }
    /* end of code for printing BDecodeContent method */

    /* do BEnc function */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);
        fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName, bufTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "    %s l;\n", lenTypeNameG);
        fprintf (src, "    l = B%s (b);\n", r->encodeContentBaseName);

        /* encode each tag/len pair if any */
        FOR_EACH_LIST_ELMT_RVS (tag, choice->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* choices are constructed */
            tagLen = TagByteLen (tag->code);

            fprintf (src, "    l += BEncConsLen (b, l);\n");

            if (tag->tclass == UNIV)
                fprintf (src, "    l += BEncTag%d (b, %s, %s, %s);\n", tagLen, classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "    l += BEncTag%d (b, %s, %s, %d);\n", tagLen, classStr, formStr, tag->code);
        }
        fprintf (src, "    return l;\n");
        fprintf (src, "}\n\n");
    }
    /* end of BEnc function */

    /* Do BDec function */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s &bytesDecoded, %s env);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "    %s elmtLen;\n", lenTypeNameG);
        fprintf (src, "    %s tag;\n", tagTypeNameG);

        /* print extra locals for redundant lengths */
        for (i = 1; (choice->tags != NULL) && (i <= LIST_COUNT (choice->tags)); i++)
        {
            fprintf (src, "    %s extraLen%d;\n", lenTypeNameG, i);
        }
        fprintf (src, "\n");

        /*  decode tag/length pair (s) */
        elmtLevel = 0;
        FOR_EACH_LIST_ELMT (tag, choice->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* choices are constructed */

            fprintf (src, "    if (BDecTag (b, bytesDecoded, env) != ");
            if (tag->tclass == UNIV)
                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "MAKE_TAG_ID (%s, %s, %d))", classStr, formStr, tag->code);
            fprintf (src, "    {\n");
	    fprintf (src, "        Asn1Error << \"%s::B%s: ERROR - wrong tag\" << std::endl;\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
            fprintf (src, "        longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "    }\n");
            fprintf (src, "    extraLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
        }

        /* decode identifying tag from choice body */
        fprintf (src, "    /*  CHOICEs are a special case - grab identifying tag */\n");
        fprintf (src, "    /*  this allows easier handling of nested CHOICEs */\n");
        fprintf (src, "    tag = BDecTag (b, bytesDecoded, env);\n");
        fprintf (src, "    elmtLen = BDecLen (b, bytesDecoded, env);\n");
        fprintf (src, "    B%s (b, tag, elmtLen, bytesDecoded, env);\n", r->decodeContentBaseName);

        /* grab any EOCs that match redundant, indef lengths */
        for (i = elmtLevel; i > 0; i--)
        {
            fprintf (src, "    if (extraLen%d == INDEFINITE_LEN)\n", i);
            fprintf (src, "        BDecEoc (b, bytesDecoded, env);\n");
        }

        fprintf (src, "}\n\n");
    }
    /* end of BDec function */

    PrintPduMemberFcns (src, hdr, r, td->cxxTypeDefInfo->className);

    /* ostream printing routine */
    if (printPrintersG)
    {
        fprintf (hdr, "  void			Print (std::ostream &os) const;\n", td->cxxTypeDefInfo->className);

        fprintf (src, "void %s::Print (std::ostream &os) const\n", td->cxxTypeDefInfo->className);
        fprintf (src, "{\n");
        /*    fprintf (src, "  os << \"{\" << std::endl;\n") */
        fprintf (src, "  switch (choiceId)\n");
        fprintf (src, "  {\n");
        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
        {
            fprintf (src, "    case %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);

            /* value notation so print the choice elmts field name */
            if (e->fieldName != NULL)
                fprintf (src, "      os << \"%s \";\n", e->fieldName);

            if (e->type->cxxTypeRefInfo->isPtr)
	    {
                fprintf (src, "      if (%s)\n", e->type->cxxTypeRefInfo->fieldName);
                fprintf (src, "        os << *%s;\n", e->type->cxxTypeRefInfo->fieldName);
                fprintf (src, "      else\n");
#ifdef KHO
                fprintf (src, "        os << \"-- void3 --\\n\";\n", e->type->cxxTypeRefInfo->fieldName);
#else
                fprintf (src, "        os << \"-- void --\";\n", e->type->cxxTypeRefInfo->fieldName);
#endif
	    }
            else
                fprintf (src, "      os << %s;\n", e->type->cxxTypeRefInfo->fieldName);

            fprintf (src, "      break;\n\n");
        }
        fprintf (src, "  } // end of switch\n");

        /*    fprintf (src, "  os << \"}\" << std::endl;\n") */
        fprintf (src, "} // %s::Print\n\n", td->cxxTypeDefInfo->className);
    }
    /* end of Print Method code */

    /* close class definition */
    fprintf (hdr, "};\n\n\n");

} /* PrintCxxChoiceDefCode */



static void
PrintCxxSeqDefCode PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, parent, seq, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *seq _AND_
    int novolatilefuncs)
{
    NamedType *e;
    char *classStr;
    char *formStr;
    char *codeStr;
    int tagLen, i;
    Tag *tag;
    TagList *tags;
    char *varName;
    CxxTRI *cxxtri;
    int elmtLevel;
    int varCount, tmpVarCount;
    int stoleChoiceTags;
    int inTailOptElmts;
    enum BasicTypeChoiceId tmpTypeId;
    NamedType *defByNamedType;
    NamedType *tmpElmt;
    int allOpt;

#ifdef _IBM_ENC_
#include "./ibm_editor/print_cxx_seq_def_code.h"
#endif /* _IBM_ENC_ */

    /* put class spec in hdr file */

    fprintf (hdr, "class %s%s\n", td->cxxTypeDefInfo->className, baseClassesG);
    fprintf (hdr, "{\n");
    fprintf (hdr, "public:\n");

    /* write out the sequence elmts */
    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
    {
        fprintf (hdr, "  ");
        PrintCxxType (hdr, mods, m, r, td, seq, e->type);
        fprintf (hdr, "%s;\n", e->type->cxxTypeRefInfo->fieldName);
    }

    fprintf (hdr, "\n");

#if META
    if (printMetaG)
    {
	fprintf (hdr, "#if META\n");
	fprintf (src, "#if META\n\n");

	fprintf (hdr, "  static const AsnSequenceTypeDesc	_desc;\n");
	fprintf (hdr, "  static const AsnSequenceMemberDesc	_mdescs[];\n");
	fprintf (hdr, "  const AsnTypeDesc		*_getdesc() const;\n");
	fprintf (hdr, "  AsnType			*_getref (const char *membername, bool create = false);\n\n");

	fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	fprintf (src, "}\n\n");

	fprintf (src, "const AsnSequenceMemberDesc %s::_mdescs[] =\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    if (printMetaG == META_backend_names)
		fprintf (src, "  AsnSequenceMemberDesc (\"%s\", &%s::_desc, %s), // `%s'\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->type->optional || e->type->defaultVal ? "true" : "false", e->fieldName ? e->fieldName : "");
	    else /* META_asn1_names */
		fprintf (src, "  AsnSequenceMemberDesc (\"%s\", &%s::_desc, %s), // `%s'\n", e->fieldName ? e->fieldName : e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->type->optional || e->type->defaultVal ? "true" : "false", e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "  AsnSequenceMemberDesc()\n");
	fprintf (src, "};\n\n");

	fprintf (src, "const AsnSequenceTypeDesc %s::_desc\n", td->cxxTypeDefInfo->className);
	fprintf (src, "(\n");
	fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	if (printMetaG == META_backend_names)
	    fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	else /* META_asn1_names */
	    fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	fprintf (src, "  AsnTypeDesc::SEQUENCE,\n");
	fprintf (src, "  create%s,\n", td->cxxTypeDefInfo->className);
	fprintf (src, "  _mdescs\n");
	fprintf (src, ");\n\n");

	fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return &_desc;\n");
	fprintf (src, "}\n\n");

	fprintf (src, "AsnType *%s::_getref (const char *membername, bool create)\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	{
	    fprintf (src, "  if (!strcmp (membername, \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
	    if (e->type->cxxTypeRefInfo->isPtr)
	    {
		fprintf (src, "  {\n");
		fprintf (src, "    if (!%s && create)\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "      %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		fprintf (src, "    return %s;\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "  }\n");
	    }
	    else
		fprintf (src, "    return &%s;\n", e->type->cxxTypeRefInfo->fieldName);
	}
	fprintf (src, "  return NULL;\n");
	fprintf (src, "}\n\n");

#if TCL
	if (printTclG)
	{
	    fprintf (hdr, "#if TCL\n");
	    fprintf (src, "#if TCL\n\n");

	    fprintf (hdr, "  int			TclGetDesc (Tcl_DString *) const;\n");
	    fprintf (hdr, "  int			TclGetVal (Tcl_Interp *) const;\n");
	    fprintf (hdr, "  int			TclSetVal (Tcl_Interp *, const char *valstr);\n");
	    fprintf (hdr, "  int			TclUnsetVal (Tcl_Interp *, const char *membname);\n\n");

	    fprintf (src, "int %s::TclGetDesc (Tcl_DString *valstr) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DStringStartSublist (valstr);\n\n");
	    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    {
		fprintf (src, "  Tcl_DStringStartSublist (valstr);\n");
		fprintf (src, "  Tcl_DStringAppendElement (valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		if (e->type->cxxTypeRefInfo->isPtr)
		    fprintf (src, "  Tcl_DStringAppendElement (valstr, %s ? \"valid\" : \"void\");\n", e->type->cxxTypeRefInfo->fieldName);
		else
		    fprintf (src, "  Tcl_DStringAppendElement (valstr, \"valid\");\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "  Tcl_DStringEndSublist (valstr);\n\n");
	    }
	    fprintf (src, "  Tcl_DStringEndSublist (valstr);\n\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclGetVal (Tcl_Interp *interp) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DString valstr;\n\n");
	    fprintf (src, "  Tcl_DStringInit (&valstr);\n\n");
	    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    {
		if (e->type->cxxTypeRefInfo->isPtr)
		{
		    fprintf (src, "  if (%s)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "  {\n");
		    fprintf (src, "    Tcl_DStringStartSublist (&valstr);\n");
		    fprintf (src, "    Tcl_DStringAppendElement (&valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    if (%s->TclGetVal (interp) != TCL_OK)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      goto Error;\n");
		    fprintf (src, "    Tcl_DStringAppendElement (&valstr, interp->result);\n");
		    fprintf (src, "    Tcl_ResetResult (interp);\n");
		    fprintf (src, "    Tcl_DStringEndSublist (&valstr);\n");
		    fprintf (src, "  }\n\n");
		}
		else
		{
		    fprintf (src, "  Tcl_DStringStartSublist (&valstr);\n");
		    fprintf (src, "  Tcl_DStringAppendElement (&valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "  if (%s.TclGetVal (interp) != TCL_OK)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    goto Error;\n");
		    fprintf (src, "  Tcl_DStringAppendElement (&valstr, interp->result);\n");
		    fprintf (src, "  Tcl_ResetResult (interp);\n");
		    fprintf (src, "  Tcl_DStringEndSublist (&valstr);\n\n");
		}
	    }
	    fprintf (src, "  Tcl_DStringResult (interp, &valstr);\n");
	    fprintf (src, "  return TCL_OK;\n\n");
	    fprintf (src, "Error:\n");
	    fprintf (src, "  Tcl_DStringFree (&valstr);\n");
	    fprintf (src, "  return TCL_ERROR;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclSetVal (Tcl_Interp *interp, const char *valstr)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  int i;\n");
	    fprintf (src, "  Args elems;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)valstr, &elems.c, &elems.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  Args* elempairs = new Args[elems.c];\n");
	    fprintf (src, "  for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    if (Tcl_SplitList (interp, elems.v[i], &elempairs[i].c, &elempairs[i].v) != TCL_OK)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    if (elempairs[i].c != 2)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"syntax error in element #%%d: expected a pair, but it's got %%d element(s)\", i, elempairs[i].c);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (const AsnSequenceMemberDesc *m=_mdescs; m->name; m++)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    int count = 0;\n");
	    fprintf (src, "    for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "      if (!strcmp (elempairs[i].v[0], m->name))\n");
	    fprintf (src, "        count++;\n");
	    fprintf (src, "    if (count > 1)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"duplicate value for member \\\"%%s\\\" in list\", m->name);\n");
	    fprintf (src, "      Tcl_SetErrorCode (interp, \"SNACC\", \"DUPMEMB\", NULL);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    if (!m->optional && count < 1)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"mandatory member \\\"%%s\\\" is missing in list\", m->name);\n");
	    fprintf (src, "      Tcl_SetErrorCode (interp, \"SNACC\", \"MISSMAND\", NULL);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    \n");
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    {
		fprintf (src, "    if (!strcmp (elempairs[i].v[0], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "    {\n");
		if (e->type->cxxTypeRefInfo->isPtr)
		{
		    fprintf (src, "      if (!%s)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "        %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		    fprintf (src, "      if (%s->TclSetVal (interp, elempairs[i].v[1]))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      {\n");
		    fprintf (src, "        delete elempairs;\n");
		    fprintf (src, "        return TCL_ERROR;\n");
		    fprintf (src, "      }\n");
		}
		else
		{
		    fprintf (src, "      if (%s.TclSetVal (interp, elempairs[i].v[1]))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      {\n");
		    fprintf (src, "        delete elempairs;\n");
		    fprintf (src, "        return TCL_ERROR;\n");
		    fprintf (src, "      }\n");
		}
		fprintf (src, "    }\n");
	    }
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  // look for unmentioned optional members and delete them:\n");
	    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    {
		if (e->type->optional || e->type->defaultVal)
		{
		    fprintf (src, "  {\n");
		    fprintf (src, "    bool present = false;\n");
		    fprintf (src, "    for (i=0; i<elems.c; i++)\n");
		    fprintf (src, "      if (!strcmp (elempairs[i].v[0], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "        present = true;\n");
		    fprintf (src, "    if (!present)\n");
		    fprintf (src, "    {\n");
		    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    }\n");
		    fprintf (src, "  }\n");
		}
	    }
	    fprintf (src, "\n");
	    fprintf (src, "  delete elempairs;\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclUnsetVal (Tcl_Interp *interp, const char *membernames)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Args elems;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)membernames, &elems.c, &elems.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (int i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	    {
		fprintf (src, "    if (!strcmp (elems.v[i], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "    {\n");
		if (e->type->optional || e->type->defaultVal)
		{
		    fprintf (src, "        delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "        %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
		}
		else
		{
		    fprintf (src, "        return _desc.mandatmemberr (interp, elems.v[i]);\n");
		}
		fprintf (src, "    }\n");
	    }
	    fprintf (src, "  }\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "#endif // TCL\n");
	    fprintf (src, "#endif // TCL\n\n");
	}
#endif /* TCL */

	fprintf (hdr, "#endif // META\n\n");
	fprintf (src, "#endif // META\n\n");
    }
#endif /* META */

    /* constructors and destructor: */

    fprintf (hdr, "			%s();\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
    {
	if (e->type->cxxTypeRefInfo->isPtr)
	    if (e->type->optional || e->type->defaultVal)
		fprintf (src, "  %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	    else
	    {
		fprintf (src, "#if TCL\n");
		fprintf (src, "  %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		fprintf (src, "#else\n");
		fprintf (src, "  %s = NULL; // incomplete initialization of mandatory element!\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "#endif // TCL\n");
	    }
    }
    fprintf (src, "}\n\n");

    fprintf (hdr, "			%s (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s::%s (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "}\n\n");

    fprintf (hdr, "			~%s();\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::~%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
	if (e->type->cxxTypeRefInfo->isPtr)
	    fprintf (src, "  delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
    fprintf (src, "}\n\n");

    /* print clone routine for ANY mgmt */
    PrintCloneMethod (hdr, src, td);

    fprintf (hdr, "  %s		&operator = (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &that)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "{\n");
    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "  if (this != &that)\n");
    fprintf (src, "  {\n");
    FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
    {
	if (e->type->cxxTypeRefInfo->isPtr)
	{
	    fprintf (src, "    if (that.%s)\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    {\n");
	    fprintf (src, "      if (!%s)\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "        %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
	    fprintf (src, "      *%s = *that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    }\n");
	    fprintf (src, "    else\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    }\n");
	}
	else
	    fprintf (src, "    %s = that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
    }
    fprintf (src, "  }\n");
    fprintf (src, "\n");
    fprintf (src, "  return *this;\n");
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s &%s::operator = (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "  // if your compiler complains here, check the -novolat option\n");
    if (novolatilefuncs)
    {
      fprintf (src, "  return *this;\n");
    }
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "}\n\n");

    /* BerEncodeContent method */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeContentBaseName, bufTypeNameG);

        fprintf (src, "%s\n", lenTypeNameG);
        fprintf (src, "%s::B%s (%s b)\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName, bufTypeNameG);

        fprintf (src, "{\n");

        /* print local vars */
        fprintf (src, "  %s totalLen = 0;\n", lenTypeNameG);
        fprintf (src, "  %s l;\n\n", lenTypeNameG);

        FOR_EACH_LIST_ELMT_RVS (e, seq->basicType->a.sequence)
        {
            cxxtri =  e->type->cxxTypeRefInfo;

            varName = cxxtri->fieldName;

            /* print optional test if nec */
            if (e->type->optional || (e->type->defaultVal != NULL))
	    {
                fprintf (src, "  if (%s (%s))\n", cxxtri->optTestRoutineName, varName);
                fprintf (src, "  {\n");
	    }

            /* encode Eoc (s) if nec */
            PrintCxxEocEncoders (src, td, e->type, "b");

            /* encode content */
            tmpTypeId = GetBuiltinType (e->type);
            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
            {
                fprintf (src, "    %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                {
                    fprintf (src, "SetTypeByOid (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }
                else
                {
                    fprintf (src, "SetTypeByInt (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }

                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else if (tmpTypeId == BASICTYPE_ANY)
            {
                fprintf (src, "    %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "SetTypeBy???(???);\n");

                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else
            {
                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                fprintf (src, "B%s (b);\n", r->encodeContentBaseName);
            }


            /* encode tag (s) & len (s) */
            PrintCxxTagAndLenEncodingCode (src, td, e->type, "l", "b");


            fprintf (src, "    totalLen += l;\n");

            /* close optional test if nec */
            if (e->type->optional || (e->type->defaultVal != NULL))
                fprintf (src, "  }\n\n");
            else
                fprintf (src, "\n");
        }
        fprintf (src, "  return totalLen;\n");
        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName);
    }
    /* end of BerEncodeContent method printing code */

    /* write BerDecodeContent to src */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s tag, %s elmtLen, %s &bytesDecoded, %s env);\n\n", r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s /*tag0*/, %s elmtLen0, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "{\n");

        /* print local vars */
        fprintf (src, "  %s tag1;\n", tagTypeNameG);
        fprintf (src, "  %s seqBytesDecoded = 0;\n", lenTypeNameG);
        /* count max number of extra length var nec */
        varCount = 0;
        FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
        {
            tmpVarCount = CxxCountVariableLevels (e->type);

            if (tmpVarCount > varCount)
                varCount = tmpVarCount;
        }
        /* write extra length vars */
        for (i = 1; i <= varCount; i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);

        /* handle empty seq */
        if ((seq->basicType->a.sequence == NULL) || LIST_EMPTY (seq->basicType->a.sequence))
        {
            fprintf (src, "  if (elmtLen0 == INDEFINITE_LEN)\n");
            fprintf (src, "    BDecEoc (b, bytesDecoded, env);\n");
            fprintf (src, "  else if (elmtLen0 != 0)\n");
            fprintf (src, "  {\n");
            fprintf (src, "     Asn1Error << \"Expected an empty sequence\" << std::endl;\n");
            fprintf (src, "     longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

/*
            forget about posssible extensions to the type
            fprintf (src, "  {\n");
            fprintf (src, "    tag1 = BDecTag (b, bytesDecoded, env);\n\n");
            fprintf (src, "    if (tag1 == EOC_TAG_ID)\n");
            fprintf (src, "      BDEC_2ND_EOC_OCTET (b, bytesDecoded, env)\n");
            fprintf (src, "    else\n");

            fprintf (src, "      BerDiscardElmt (b, bytesDecoded, env);\n\n");
            fprintf (src, "  }\n");
            fprintf (src, "  else\n");
            fprintf (src, "  {\n");
            fprintf (src, "    BufSkip (b, elmtLen0);\n");
            fprintf (src, "    bytesDecoded%d += elmtLen0;\n");
            fprintf (src, "  }\n");
*/
        }
        else
        {
            /*  check if all elmts are optional */
            AsnListFirst (seq->basicType->a.sequence);
            inTailOptElmts = IsTailOptional (seq->basicType->a.sequence);
            e = (NamedType*)FIRST_LIST_ELMT (seq->basicType->a.sequence);

            tmpTypeId = GetBuiltinType (e->type);

            if (!inTailOptElmts)
            {
                if (((tmpTypeId == BASICTYPE_ANY) || (tmpTypeId == BASICTYPE_ANYDEFINEDBY)) && (CountTags (e->type) == 0))
                {
                    if ((e->type->optional) && (e != (NamedType*)LAST_LIST_ELMT (seq->basicType->a.sequence)))
                        fprintf (src, "<untagged optional ANY - you must fix this>\n");
                }
                else
                    fprintf (src, "  tag1 = BDecTag (b, seqBytesDecoded, env);\n\n");
            }
            else
            {
                fprintf (src, "  if (elmtLen0 == 0)\n");
                fprintf (src, "    return;\n");
                fprintf (src, "  else\n");
                fprintf (src, "  {\n");
                if (((tmpTypeId == BASICTYPE_ANY) || (tmpTypeId == BASICTYPE_ANYDEFINEDBY)) && (CountTags (e->type) == 0))
                {
                    if ((e->type->optional) && (e != (NamedType*)LAST_LIST_ELMT (seq->basicType->a.sequence)))
                        fprintf (src, "<untagged optional ANY - you must fix this>\n");
                }
                else
                    fprintf (src, "    tag1 = BDecTag (b, seqBytesDecoded, env);\n\n");
                fprintf (src, "    if ((elmtLen0 == INDEFINITE_LEN) && (tag1 == EOC_TAG_ID))\n");
                fprintf (src, "    {\n");
                fprintf (src, "      BDEC_2ND_EOC_OCTET (b, seqBytesDecoded, env)\n");
                fprintf (src, "      bytesDecoded += seqBytesDecoded;\n");
                fprintf (src, "      return;\n");
                fprintf (src, "    }\n");
                fprintf (src, "  }\n\n");
            }


            FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
            {
                cxxtri =  e->type->cxxTypeRefInfo;
                elmtLevel = 0;

                tags = GetTags (e->type, &stoleChoiceTags);

                /*            if (inTailOptElmts)
                              fprintf (src, " (!seqDone) && ");
                              */
                if (LIST_EMPTY (tags))
                    fprintf (src, "  // ANY type\n");
                else
                {
                    tag = (Tag*)FIRST_LIST_ELMT (tags);
                    classStr = Class2ClassStr (tag->tclass);
                    codeStr = Code2UnivCodeStr (tag->code);
                    formStr = Form2FormStr (tag->form);

                    fprintf (src, "  if (");
                    if (tag->tclass == UNIV)
                    {
                        if (tag->form == ANY_FORM)
                        {
                            fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %s))\n", classStr, Form2FormStr (PRIM), codeStr);
                            fprintf (src, "    || (tag1 == MAKE_TAG_ID (%s, %s, %s))", classStr, Form2FormStr (CONS), codeStr);
                        }
                        else
                            fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, codeStr);
                    }
                    else
                    {
                        if (tag->form == ANY_FORM)
                        {
                            fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %d))\n", classStr, Form2FormStr (PRIM), tag->code);
                            fprintf (src, "    || (tag1 == MAKE_TAG_ID (%s, %s, %d))", classStr, Form2FormStr (CONS), tag->code);
                        }
                        else
                            fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %d))", classStr, formStr, tag->code);
                    }


                    /* now decode extra tags/length pairs */
                    AsnListFirst (tags);
                    AsnListNext (tags);
                    if (stoleChoiceTags)
                    {
                        FOR_REST_LIST_ELMT (tag, tags)
                        {
                            fprintf (src, "\n    || ");
                            classStr = Class2ClassStr (tag->tclass);
                            codeStr = Code2UnivCodeStr (tag->code);
                            formStr = Form2FormStr (tag->form);

                            if (tag->tclass == UNIV)
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %s))\n", classStr, Form2FormStr (PRIM), codeStr);
                                    fprintf (src, "    || (tag1 == MAKE_TAG_ID (%s, %s, %s))", classStr, Form2FormStr (CONS), codeStr);
                                }
                                else
                                    fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, codeStr);
                            }
                            else
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %d))\n", classStr, Form2FormStr (PRIM), tag->code);
                                    fprintf (src, "    || (tag1 == MAKE_TAG_ID (%s, %s, %d))", classStr, Form2FormStr (CONS), tag->code);
                                }
                                else
                                    fprintf (src, "(tag1 == MAKE_TAG_ID (%s, %s, %d))", classStr, formStr, tag->code);
                            }
                        }
                        fprintf (src, ")\n");
                        fprintf (src, "  {\n");
                        fprintf (src, "    elmtLen%d = BDecLen (b, seqBytesDecoded, env);\n", ++elmtLevel);
                    }

                    else /* didn't steal nested choice's tags */
                    {
                        fprintf (src, ")\n");
                        fprintf (src, "  {\n");
                        fprintf (src, "    elmtLen%d = BDecLen (b, seqBytesDecoded, env);\n", ++elmtLevel);

                        FOR_REST_LIST_ELMT (tag, tags)
                        {
                            classStr = Class2ClassStr (tag->tclass);
                            codeStr = Code2UnivCodeStr (tag->code);
                            formStr = Form2FormStr (tag->form);

                            fprintf (src, "    tag1 = BDecTag (b, seqBytesDecoded, env);\n\n");
                            if (tag->tclass == UNIV)
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "    if ((tag1 != MAKE_TAG_ID (%s, %s, %s))\n", classStr, Form2FormStr (PRIM), codeStr);
                                    fprintf (src, "       && (tag1 != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), codeStr);
                                }
                                else
                                    fprintf (src, "    if (tag1 != MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, codeStr);
                            }
                            else
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "    if ((tag1 != MAKE_TAG_ID (%s, %s, %d))\n",  classStr, Form2FormStr (PRIM), tag->code);
                                    fprintf (src, "      && (tag1 != MAKE_TAG_ID (%s, %s, %d)))\n", classStr, Form2FormStr (CONS), tag->code);
                                }
                                else
                                    fprintf (src, "    if (tag1 != MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
                            }

                            fprintf (src, "    {\n");
                            fprintf (src, "       Asn1Error << \"Unexpected Tag\" << std::endl;\n");
                            fprintf (src, "       longjmp (env, %d);\n", longJmpValG--);
                            fprintf (src, "    }\n\n");
                            fprintf (src, "    elmtLen%d = BDecLen (b, seqBytesDecoded, env);\n", ++elmtLevel);
                        }
                    }
                }
                /*
                 * if this seq element is CHOICE &&
                 * we didn't steal its tags then we must grab
                 * the key tag out of the contained CHOICE
                 */
                if (!stoleChoiceTags && (GetBuiltinType (e->type) == BASICTYPE_CHOICE))
                {
                    fprintf (src, "    tag1 = BDecTag (b, seqBytesDecoded, env);\n");
                    fprintf (src, "    elmtLen%d = BDecLen (b, seqBytesDecoded, env);\n", ++elmtLevel);
                }



                varName = cxxtri->fieldName;

                /* decode content */
                if (cxxtri->isPtr)
                    fprintf (src, "    %s = new %s;\n", varName, cxxtri->className);


                /* decode content */
                tmpTypeId = GetBuiltinType (e->type);
                if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
                {
                    /*
                     * must check for another EOC for ANYs
                     * since the any decode routines decode
                     * their own first tag/len pair
                     */
                    elmtLevel++;
                    fprintf (src, "    %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");

                    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                    if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                    {
                        fprintf (src, "SetTypeByOid (");
                        if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                            fprintf (src, " *");
                        fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                    }
                    else
                    {
                        fprintf (src, "SetTypeByInt (");
                        if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                            fprintf (src, " *");
                        fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                    }

                    fprintf (src, "    %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "B%s (b, seqBytesDecoded, env);\n",  r->decodeBaseName);
                }
                else if (tmpTypeId == BASICTYPE_ANY)
                {
                    /*
                     * must check for another EOC for ANYs
                     * since the any decode routines decode
                     * their own first tag/len pair
                     */
                    elmtLevel++;

                    fprintf (src, "    %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "SetTypeBy???(???);\n");

                    fprintf (src, "    %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "B%s (b, seqBytesDecoded, env);\n",  r->decodeBaseName);
                }
                else
                {
                    fprintf (src, "    %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");

                    fprintf (src, "B%s (b, tag1, elmtLen%d, seqBytesDecoded, env);\n",  r->decodeContentBaseName, elmtLevel);
                }

                /* decode Eoc (s) */
                for (i = elmtLevel-1; i > 0; i--)
                {
                    fprintf (src, "    if (elmtLen%d == INDEFINITE_LEN)\n", i);
                    fprintf (src, "      BDecEoc (b, seqBytesDecoded, env);\n\n");
                }

                /*
                 * print code for getting the next tag
                 */
                inTailOptElmts = RestAreTailOptional (seq->basicType->a.sequence);
                if  (e != (NamedType*)LAST_LIST_ELMT (seq->basicType->a.sequence))
                {
                    tmpElmt = (NamedType*)NEXT_LIST_ELMT (seq->basicType->a.sequence);
                    tmpTypeId = GetBuiltinType (tmpElmt->type);
                    if (!inTailOptElmts)
                    {
                        if ((tmpTypeId == BASICTYPE_ANY || tmpTypeId == BASICTYPE_ANYDEFINEDBY) && CountTags (tmpElmt->type) == 0)
                        {
                            /* don't get a tag since ANY's decode their own */
                            if (e->type->optional || (tmpElmt->type->optional && tmpElmt != (NamedType*)LAST_LIST_ELMT (seq->basicType->a.sequence)))
                                /* let this cause a compile error in the generated code */
                                fprintf (src, "  <problems with untagged ANY that is optional or follows an optional sequence element - you must fix this>\n");
                        }
                        else
                            fprintf (src, "    tag1 = BDecTag (b, seqBytesDecoded, env);\n");
                    }
                    else
                    {
                        fprintf (src, "    if (seqBytesDecoded == elmtLen0)\n");
                        fprintf (src, "    {\n");
                        fprintf (src, "      bytesDecoded += seqBytesDecoded;\n");
                        fprintf (src, "      return;\n");
                        fprintf (src, "    }\n");
                        fprintf (src, "    else\n");
                        fprintf (src, "    {\n");

                        if ((tmpTypeId == BASICTYPE_ANY || tmpTypeId == BASICTYPE_ANYDEFINEDBY) && !CountTags (tmpElmt->type))
                        {
                            /* don't get a tag since ANY's decode their own */
                            if (e->type->optional || (tmpElmt->type->optional && tmpElmt != (NamedType *)LAST_LIST_ELMT (seq->basicType->a.sequence)))
                            {
                                /*
                                 * let this cause a compile error in the generated code
                                 */
                                fprintf (src, "  <problems with untagged ANY that is optional or follows an optional sequence element - you must fix this>\n");
                            }
                            fprintf (src, "      tag1 = b.PeekByte();\n\n");
                            fprintf (src, "      if ((elmtLen0 == INDEFINITE_LEN) && (tag1 == EOC_TAG_ID))\n");
                            fprintf (src, "      {\n");
                            fprintf (src, "        BDecEoc (b, seqBytesDecoded, env);\n\n");
                            fprintf (src, "        bytesDecoded += seqBytesDecoded;\n");
                            fprintf (src, "        return;\n");
                            fprintf (src, "      }\n");

                        }
                        else
                        {
                            fprintf (src, "      tag1 = BDecTag (b, seqBytesDecoded, env);\n\n");
                            fprintf (src, "      if ((elmtLen0 == INDEFINITE_LEN) && (tag1 == EOC_TAG_ID))\n");
                            fprintf (src, "      {\n");
                            fprintf (src, "        BDEC_2ND_EOC_OCTET (b, seqBytesDecoded, env)\n");
                            fprintf (src, "        bytesDecoded += seqBytesDecoded;\n");
                            fprintf (src, "        return;\n");
                            fprintf (src, "      }\n");
                        }
                        fprintf (src, "    }\n");

                    }
                }


                /*
                 * close tag check if (if there is one) and
                 * print else clause to handle missing non-optional elmt
                 * errors
                 */
                tmpTypeId = GetBuiltinType (e->type);
                if ((tmpTypeId == BASICTYPE_ANYDEFINEDBY || tmpTypeId == BASICTYPE_ANY) && !CountTags (e->type))
                {
                    /* do nothing - no tag check if stmt to close */
                    fprintf (src, "\n\n");
                }
                else if (!e->type->optional && !e->type->defaultVal)
                {
                    fprintf (src, "  }\n"); /* end of tag check if */
                    fprintf (src, "  else\n");
                    fprintf (src, "  {\n");
                    fprintf (src, "    Asn1Error << \"ERROR - SEQUENCE is missing non-optional elmt.\" << std::endl;\n");
                    fprintf (src, "    longjmp (env, %d);\n", longJmpValG--);
                    fprintf (src, "  }\n\n");
                }
                else
                    fprintf (src, "  }\n\n"); /* end of tag check if */

                FreeTags (tags);
            }

            /* for last elmt only */
            fprintf (src, "  bytesDecoded += seqBytesDecoded;\n");
            fprintf (src, "  if (elmtLen0 == INDEFINITE_LEN)\n");
            fprintf (src, "  {\n");
            fprintf (src, "    BDecEoc (b, bytesDecoded, env);\n");
            fprintf (src, "    return;\n");
            fprintf (src, "  }\n");
            fprintf (src, "  else if (seqBytesDecoded != elmtLen0)\n");
            fprintf (src, "  {\n");
            fprintf (src, "    Asn1Error << \"ERROR - Length discrepancy on sequence.\" << std::endl;\n");
            fprintf (src, "    longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");
            fprintf (src, "  else\n");
            fprintf (src, "    return;\n");

        } /* end of non-empty set else clause */

        fprintf (src, "} // %s::B%s\n\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName);
    }
    /* end of code for printing ber decode content method */

    /* do BEnc function */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);

        fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName,  bufTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s l;\n", lenTypeNameG);
        fprintf (src, "  l = B%s (b);\n", r->encodeContentBaseName);

        /* encode each tag/len pair if any */
        FOR_EACH_LIST_ELMT_RVS (tag, seq->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* seq's are constructed */
            tagLen = TagByteLen (tag->code);

            fprintf (src, "  l += BEncConsLen (b, l);\n");

            if (tag->tclass == UNIV)
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %s);\n", tagLen, classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %d);\n", tagLen, classStr, formStr, tag->code);
        }
        fprintf (src, "  return l;\n");
        fprintf (src, "}\n\n");
    }
    /* end of BEnc function */

    /* Do BDec function */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s &bytesDecoded, %s env);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeBaseName,  bufTypeNameG, lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s tag;\n", tagTypeNameG);

        /* print extra locals for redundant lengths */
        for (i = 1; (seq->tags != NULL) && (i <= LIST_COUNT (seq->tags)); i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);
        fprintf (src, "\n");

        /*  decode tag/length pair (s) */
        elmtLevel = 0;
        FOR_EACH_LIST_ELMT (tag, seq->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* seqs are constructed */

            fprintf (src, "  if ((tag = BDecTag (b, bytesDecoded, env)) != ");

            if (tag->tclass == UNIV)
                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
            fprintf (src, "  {\n");
	    fprintf (src, "    Asn1Error << \"%s::B%s: ERROR - wrong tag\" << std::endl;\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
            fprintf (src, "    longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

            fprintf (src, "  elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
        }

        fprintf (src, "  B%s (b, tag, elmtLen%d, bytesDecoded, env);\n", r->decodeContentBaseName, elmtLevel);

        /* grab any EOCs that match redundant, indef lengths */
        for (i = elmtLevel-1; i > 0; i--)
        {
            fprintf (src, "  if (elmtLen%d == INDEFINITE_LEN)\n", i);
            fprintf (src, "    BDecEoc (b, bytesDecoded, env);\n");
        }

        fprintf (src, "}\n\n");
    }
    /* end of BDec function */

    PrintPduMemberFcns (src, hdr, r, td->cxxTypeDefInfo->className);

    /* write code for printing */
    if (printPrintersG)
    {
        fprintf (hdr, "  void		Print (std::ostream &os) const;\n");

        fprintf (src, "void %s::Print (std::ostream &os) const\n", td->cxxTypeDefInfo->className);
        fprintf (src, "{\n");
        allOpt = AllElmtsOptional (seq->basicType->a.sequence);
        if (allOpt)
            fprintf (src, "  int nonePrinted = true;\n");
        fprintf (src, "  os << \"{ -- SEQUENCE --\" << std::endl;\n");
        fprintf (src, "  indentG += stdIndentG;\n\n");

        FOR_EACH_LIST_ELMT (e, seq->basicType->a.sequence)
        {
            inTailOptElmts = IsTailOptional (seq->basicType->a.sequence);

            if (e->type->cxxTypeRefInfo->isPtr)
                fprintf (src, "  if (%s (%s))\n", cxxtri->optTestRoutineName, e->type->cxxTypeRefInfo->fieldName);

	    fprintf (src, "  {\n");

            if (allOpt)
            {
                if (e != FIRST_LIST_ELMT (seq->basicType->a.sequence))
                {
                    fprintf (src, "    if (!nonePrinted)\n");
                    fprintf (src, "      os << \",\" << std::endl;\n");
                }
                fprintf (src, "    nonePrinted = false;\n", i);
            }
            else if (inTailOptElmts) /* cannot be first elmt ow allOpt is true */
                fprintf (src, "    os << \",\"<< std::endl;\n");

            fprintf (src, "    Indent (os, indentG);\n");

            if (e->fieldName != NULL)
                fprintf (src, "    os << \"%s \";\n", e->fieldName);

            if (e->type->cxxTypeRefInfo->isPtr)
                fprintf (src, "    os << *%s;\n", e->type->cxxTypeRefInfo->fieldName);
            else
                fprintf (src, "    os << %s;\n", e->type->cxxTypeRefInfo->fieldName);

#ifdef KHO
            if (e != LAST_LIST_ELMT (seq->basicType->a.sequence)&&(!e->type->cxxTypeRefInfo->isPtr) )
                fprintf (src, "    os << \",\" << std::endl;\n");
#else
            if (e != LAST_LIST_ELMT (seq->basicType->a.sequence) && !inTailOptElmts && !NextIsTailOptional (seq->basicType->a.sequence))
                fprintf (src, "    os << \",\" << std::endl;\n");
#endif

	    fprintf (src, "  }\n");

            if (e->type->cxxTypeRefInfo->isPtr)
	    {
		fprintf (src, "  else\n");
#ifdef KHO
                fprintf (src, "  {\n");
                fprintf (src, "    Indent (os, indentG);\n");
                if (e->fieldName != NULL)
                  fprintf (src, "    os << \"%s \";\n", e->fieldName);
		fprintf (src, "    os << \"-- void --\";\n");
    		if (e != LAST_LIST_ELMT (seq->basicType->a.sequence))
                   fprintf (src, "    os << \",\" << std::endl;\n");
                else
                   fprintf (src, "    os << std::endl;\n");
		fprintf (src, "  }\n");
#else
		fprintf (src, "    os << \"-- void --\";\n");
#endif
	    }

	    fprintf (src, "\n");

            if (e == LAST_LIST_ELMT (seq->basicType->a.sequence))
                fprintf (src, "  os << std::endl;\n");
        }

        fprintf (src, "  indentG -= stdIndentG;\n");
        fprintf (src, "  Indent (os, indentG);\n");
        fprintf (src, "  os << \"}\";\n");
        fprintf (src, "} // %s::Print\n\n\n", td->cxxTypeDefInfo->className);
    }
    /* end of print method code printer */

    /* close class definition */
    fprintf (hdr, "};\n\n\n");

} /* PrintCxxSeqDefCode */


static void
PrintCxxSetDefCode PARAMS ((src, hdr, mods, m, r, td, parent, set, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *set _AND_
    int novolatilefuncs)
{
    NamedType *e;
    char *classStr;
    char *formStr;
    char *codeStr;
    int tagLen, i;
    Tag *tag;
    TagList *tags;
    char *varName;
    CxxTRI *cxxtri;
    int elmtLevel;
    int varCount, tmpVarCount;
    int stoleChoiceTags;
    int inTailOptElmts;
    int mandatoryElmtCount;
    enum BasicTypeChoiceId tmpTypeId;
    NamedType *defByNamedType;
    int allOpt;

    /* put class spec in hdr file */

    fprintf (hdr, "class %s%s\n", td->cxxTypeDefInfo->className, baseClassesG);
    fprintf (hdr, "{\n");
    fprintf (hdr, "public:\n");

    /* write out the set elmts */
    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
    {
        fprintf (hdr, "  ");
        PrintCxxType (hdr, mods, m, r, td, set, e->type);
        fprintf (hdr, "%s;\n", e->type->cxxTypeRefInfo->fieldName);
    }

    fprintf (hdr, "\n");

#if META
    if (printMetaG)
    {
	fprintf (hdr, "#if META\n");
	fprintf (src, "#if META\n\n");

	fprintf (hdr, "  static const AsnSetTypeDesc	_desc;\n");
	fprintf (hdr, "  static const AsnSetMemberDesc	_mdescs[];\n");
	fprintf (hdr, "  const AsnTypeDesc		*_getdesc() const;\n");
	fprintf (hdr, "  AsnType			*_getref (const char *membername, bool create = false);\n\n");

	fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	fprintf (src, "}\n\n");

	fprintf (src, "const AsnSetMemberDesc %s::_mdescs[] =\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    if (printMetaG == META_backend_names)
		fprintf (src, "  AsnSetMemberDesc (\"%s\", &%s::_desc, %s), // `%s'\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->type->optional || e->type->defaultVal ? "true" : "false", e->fieldName ? e->fieldName : "");
	    else /* META_asn1_names */
		fprintf (src, "  AsnSetMemberDesc (\"%s\", &%s::_desc, %s), // `%s'\n", e->fieldName ? e->fieldName : e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className, e->type->optional || e->type->defaultVal ? "true" : "false", e->type->cxxTypeRefInfo->fieldName);
	fprintf (src, "  AsnSetMemberDesc()\n");
	fprintf (src, "};\n\n");

	fprintf (src, "const AsnSetTypeDesc %s::_desc\n", td->cxxTypeDefInfo->className);
	fprintf (src, "(\n");
	fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	if (printMetaG == META_backend_names)
	    fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	else /* META_asn1_names */
	    fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	fprintf (src, "  AsnTypeDesc::SET,\n");
	fprintf (src, "  create%s,\n", td->cxxTypeDefInfo->className);
	fprintf (src, "  _mdescs\n");
	fprintf (src, ");\n\n");

	fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return &_desc;\n");
	fprintf (src, "}\n\n");

	fprintf (src, "AsnType *%s::_getref (const char *membername, bool create)\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	{
	    fprintf (src, "  if (!strcmp (membername, \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
	    if (e->type->cxxTypeRefInfo->isPtr)
	    {
		fprintf (src, "  {\n");
		fprintf (src, "    if (!%s && create)\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "      %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		fprintf (src, "    return %s;\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "  }\n");
	    }
	    else
		fprintf (src, "    return &%s;\n", e->type->cxxTypeRefInfo->fieldName);
	}
	fprintf (src, "  return NULL;\n");
	fprintf (src, "}\n\n");

#if TCL
	if (printTclG)
	{
	    fprintf (hdr, "#if TCL\n");
	    fprintf (src, "#if TCL\n\n");

	    fprintf (hdr, "  int			TclGetDesc (Tcl_DString *) const;\n");
	    fprintf (hdr, "  int			TclGetVal (Tcl_Interp *) const;\n");
	    fprintf (hdr, "  int			TclSetVal (Tcl_Interp *, const char *valstr);\n");
	    fprintf (hdr, "  int			TclUnsetVal (Tcl_Interp *, const char *membernames);\n\n");

	    fprintf (src, "int %s::TclGetDesc (Tcl_DString *valstr) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DStringStartSublist (valstr);\n\n");
	    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    {
		fprintf (src, "  Tcl_DStringStartSublist (valstr);\n");
		fprintf (src, "  Tcl_DStringAppendElement (valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		if (e->type->cxxTypeRefInfo->isPtr)
		    fprintf (src, "  Tcl_DStringAppendElement (valstr, %s ? \"valid\" : \"void\");\n", e->type->cxxTypeRefInfo->fieldName);
		else
		    fprintf (src, "  Tcl_DStringAppendElement (valstr, \"valid\");\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "  Tcl_DStringEndSublist (valstr);\n\n");
	    }
	    fprintf (src, "  Tcl_DStringEndSublist (valstr);\n\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclGetVal (Tcl_Interp *interp) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DString valstr;\n\n");
	    fprintf (src, "  Tcl_DStringInit (&valstr);\n\n");
	    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    {
		if (e->type->cxxTypeRefInfo->isPtr)
		{
		    fprintf (src, "  if (%s)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "  {\n");
		    fprintf (src, "    Tcl_DStringStartSublist (&valstr);\n");
		    fprintf (src, "    Tcl_DStringAppendElement (&valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    if (%s->TclGetVal (interp) != TCL_OK)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      goto Error;\n");
		    fprintf (src, "    Tcl_DStringAppendElement (&valstr, interp->result);\n");
		    fprintf (src, "    Tcl_ResetResult (interp);\n");
		    fprintf (src, "    Tcl_DStringEndSublist (&valstr);\n");
		    fprintf (src, "  }\n\n");
		}
		else
		{
		    fprintf (src, "  Tcl_DStringStartSublist (&valstr);\n");
		    fprintf (src, "  Tcl_DStringAppendElement (&valstr, \"%s\");\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "  if (%s.TclGetVal (interp) != TCL_OK)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    goto Error;\n");
		    fprintf (src, "  Tcl_DStringAppendElement (&valstr, interp->result);\n");
		    fprintf (src, "  Tcl_ResetResult (interp);\n");
		    fprintf (src, "  Tcl_DStringEndSublist (&valstr);\n\n");
		}
	    }
	    fprintf (src, "  Tcl_DStringResult (interp, &valstr);\n");
	    fprintf (src, "  return TCL_OK;\n\n");
	    fprintf (src, "Error:\n");
	    fprintf (src, "  Tcl_DStringFree (&valstr);\n");
	    fprintf (src, "  return TCL_ERROR;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclSetVal (Tcl_Interp *interp, const char *valstr)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  int i;\n");
	    fprintf (src, "  Args elems;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)valstr, &elems.c, &elems.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  Args* elempairs = new Args[elems.c];\n");
	    fprintf (src, "  for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    if (Tcl_SplitList (interp, elems.v[i], &elempairs[i].c, &elempairs[i].v) != TCL_OK)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    if (elempairs[i].c != 2)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"syntax error in element #%%d: expected a pair, but it's got %%d element(s)\", i, elempairs[i].c);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (const AsnSetMemberDesc *m=_mdescs; m->name; m++)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    int count = 0;\n");
	    fprintf (src, "    for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "      if (!strcmp (elempairs[i].v[0], m->name))\n");
	    fprintf (src, "        count++;\n");
	    fprintf (src, "    if (count > 1)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"duplicate value for member \\\"%%s\\\" in list\", m->name);\n");
	    fprintf (src, "      Tcl_SetErrorCode (interp, \"SNACC\", \"DUPMEMB\", NULL);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    if (!m->optional && count < 1)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      sprintf (interp->result, \"mandatory member \\\"%%s\\\" is missing in list\", m->name);\n");
	    fprintf (src, "      Tcl_SetErrorCode (interp, \"SNACC\", \"MISSMAND\", NULL);\n");
	    fprintf (src, "      delete elempairs;\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    \n");
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    {
		fprintf (src, "    if (!strcmp (elempairs[i].v[0], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "    {\n");
		if (e->type->cxxTypeRefInfo->isPtr)
		{
		    fprintf (src, "      if (!%s)\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "        %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		    fprintf (src, "      if (%s->TclSetVal (interp, elempairs[i].v[1]))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      {\n");
		    fprintf (src, "        delete elempairs;\n");
		    fprintf (src, "        return TCL_ERROR;\n");
		    fprintf (src, "      }\n");
		}
		else
		{
		    fprintf (src, "      if (%s.TclSetVal (interp, elempairs[i].v[1]))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      {\n");
		    fprintf (src, "        return TCL_ERROR;\n");
		    fprintf (src, "        delete elempairs;\n");
		    fprintf (src, "      }\n");
		}
		fprintf (src, "    }\n");
	    }
	    fprintf (src, "  }\n");
	    fprintf (src, "\n");
	    fprintf (src, "  // look for unmentioned optional members and delete them:\n");
	    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    {
		if (e->type->optional || e->type->defaultVal)
		{
		    fprintf (src, "  {\n");
		    fprintf (src, "    bool present = false;\n");
		    fprintf (src, "    for (i=0; i<elems.c; i++)\n");
		    fprintf (src, "      if (!strcmp (elempairs[i].v[0], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "        present = true;\n");
		    fprintf (src, "    if (!present)\n");
		    fprintf (src, "    {\n");
		    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "    }\n");
		    fprintf (src, "  }\n");
		}
	    }
	    fprintf (src, "\n");
	    fprintf (src, "  delete elempairs;\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclUnsetVal (Tcl_Interp *interp, const char *membernames)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Args elems;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)membernames, &elems.c, &elems.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (int i=0; i<elems.c; i++)\n");
	    fprintf (src, "  {\n");
	    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	    {
		fprintf (src, "    if (!strcmp (elems.v[i], \"%s\"))\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "    {\n");
		if (e->type->optional || e->type->defaultVal)
		{
		    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
		    fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
		}
		else
		{
		    fprintf (src, "      return _desc.mandatmemberr (interp, elems.v[i]);\n");
		}
		fprintf (src, "    }\n");
	    }
	    fprintf (src, "  }\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "#endif // TCL\n");
	    fprintf (src, "#endif // TCL\n\n");
	}
#endif /* TCL */

	fprintf (hdr, "#endif // META\n\n");
	fprintf (src, "#endif // META\n\n");
    }
#endif /* META */

    /* constructors and destructor: */

    fprintf (hdr, "			%s();\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
    {
	if (e->type->cxxTypeRefInfo->isPtr)
	    if (e->type->optional || e->type->defaultVal)
		fprintf (src, "  %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	    else
	    {
		fprintf (src, "#if TCL\n");
		fprintf (src, "  %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
		fprintf (src, "#else\n");
		fprintf (src, "  %s = NULL; // incomplete initialization of mandatory element!\n", e->type->cxxTypeRefInfo->fieldName);
		fprintf (src, "#endif // TCL\n");
	    }
    }
    fprintf (src, "}\n\n");

    fprintf (hdr, "			%s (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "%s::%s (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s::%s (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "}\n\n");

    fprintf (hdr, "			~%s();\n", td->cxxTypeDefInfo->className);

    fprintf (src, "%s::~%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
	if (e->type->cxxTypeRefInfo->isPtr)
	    fprintf (src, "  delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
    fprintf (src, "}\n\n");

    /* print clone routine for ANY mgmt */
    PrintCloneMethod (hdr, src, td);

    fprintf (hdr, "  %s		&operator = (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &that)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "{\n");
    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "  if (this != &that)\n");
    fprintf (src, "  {\n");
    FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
    {
	if (e->type->cxxTypeRefInfo->isPtr)
	{
	    fprintf (src, "    if (that.%s)\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    {\n");
	    fprintf (src, "      if (!%s)\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "        %s = new %s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->className);
	    fprintf (src, "      *%s = *that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    }\n");
	    fprintf (src, "    else\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
	    fprintf (src, "    }\n");
	}
	else
	    fprintf (src, "    %s = that.%s;\n", e->type->cxxTypeRefInfo->fieldName, e->type->cxxTypeRefInfo->fieldName);
    }
    fprintf (src, "  }\n");
    fprintf (src, "\n");
    fprintf (src, "  return *this;\n");
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s &%s::operator = (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "  // if your compiler complains here, check the -novolat option\n");
    if (novolatilefuncs)
    {
      fprintf (src, "  return *this;\n");
    }
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "}\n\n");

    /* BerEncode */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeContentBaseName, bufTypeNameG);

        fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeContentBaseName, bufTypeNameG);
        fprintf (src, "{\n");

        /* print local vars */
        fprintf (src, "  %s totalLen = 0;\n", lenTypeNameG);
        fprintf (src, "  %s l;\n\n", lenTypeNameG);

        FOR_EACH_LIST_ELMT_RVS (e, set->basicType->a.set)
        {
            cxxtri =  e->type->cxxTypeRefInfo;

            varName = cxxtri->fieldName;

            /* print optional test if nec*/
            if (e->type->optional || (e->type->defaultVal != NULL))
	    {
                fprintf (src, "  if (%s (%s))\n", cxxtri->optTestRoutineName, varName);
                fprintf (src, "  {\n");
	    }

            /* encode Eoc (s) if nec */
            PrintCxxEocEncoders (src, td, e->type, "b");

            /* encode content */
            tmpTypeId = GetBuiltinType (e->type);
            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
            {
                fprintf (src, "    %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                {
                    fprintf (src, "SetTypeByOid (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }
                else
                {
                    fprintf (src, "SetTypeByInt (");
                    if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                        fprintf (src, " *");
                    fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                }

                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else if (tmpTypeId == BASICTYPE_ANY)
            {
                fprintf (src, "    %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "SetTypeBy???(???);\n");

                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");
                fprintf (src, "B%s (b);\n", r->encodeBaseName);
            }
            else
            {
                fprintf (src, "    l = %s", varName);
                if (cxxtri->isPtr)
                    fprintf (src, "->");
                else
                    fprintf (src, ".");

                fprintf (src, "B%s (b);\n", r->encodeContentBaseName);
            }

            /* encode tag (s) & len (s) */
            PrintCxxTagAndLenEncodingCode (src, td, e->type, "l", "b");

            fprintf (src, "    totalLen += l;\n");

            /* close optional test if nec */
            if (e->type->optional || (e->type->defaultVal != NULL))
                fprintf (src, "  }\n\n");
            else
                fprintf (src, "\n");
        }
        fprintf (src, "  return totalLen;\n");
        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName);
    }
    /* end of BerEncodeContent */

    /* write BerDecodeContent */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s tag, %s elmtLen, %s &bytesDecoded, %s env);\n\n", r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s /*tag0*/, %s elmtLen0, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");

        /* print local vars */
        fprintf (src, "  %s tag1;\n", tagTypeNameG);
        fprintf (src, "  %s setBytesDecoded = 0;\n", lenTypeNameG);
        fprintf (src, "  unsigned int mandatoryElmtsDecoded = 0;\n");
        /* count max number of extra length var nec */
        varCount = 0;
        FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
        {
            tmpVarCount = CxxCountVariableLevels (e->type);
            if (tmpVarCount > varCount)
                varCount = tmpVarCount;
        }
        /* write extra length vars */
        for (i = 1; i <= varCount; i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);
        fprintf (src, "\n");

        /* handle empty set */
        if ((set->basicType->a.set == NULL) || LIST_EMPTY (set->basicType->a.set))
        {
            fprintf (src, "  if (elmtLen0 == INDEFINITE_LEN)\n");
            fprintf (src, "    BDecEoc (b, bytesDecoded, env);\n");
            fprintf (src, "  else if (elmtLen0 != 0)\n");
            fprintf (src, "  {\n");
            fprintf (src, "     Asn1Error << \"Expected an empty sequence\" << std::endl;\n");
            fprintf (src, "     longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

/*   forget about potential extension types for now
            fprintf (src, "  if (elmtLen0 == INDEFINITE_LEN)\n");
            fprintf (src, "  {\n");
            fprintf (src, "    tag1 = BDecTag (b, bytesDecoded, env);\n\n");
            fprintf (src, "    if (tag1 == EOC_TAG_ID)\n");
            fprintf (src, "      BDEC_2ND_EOC_OCTET (b, bytesDecoded, env)\n");
            fprintf (src, "    else\n");
            fprintf (src, "      BerDiscardElmt (b, bytesDecoded, env);\n\n");
            fprintf (src, "  }\n");
            fprintf (src, "  else\n");
            fprintf (src, "  {\n");
            fprintf (src, "    BufSkip (b, elmtLen0);\n");
            fprintf (src, "    bytesDecoded += elmtLen0;\n");
            fprintf (src, "  }\n");
*/
        }
        else
        {
            fprintf (src, "  for (; (setBytesDecoded < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )\n");
            fprintf (src, "  {\n");
            fprintf (src, "    tag1 = BDecTag (b, setBytesDecoded, env);\n\n");
            fprintf (src, "    if ((elmtLen0 == INDEFINITE_LEN) && (tag1 == EOC_TAG_ID))\n");
            fprintf (src, "    {\n");
            fprintf (src, "      BDEC_2ND_EOC_OCTET (b, setBytesDecoded, env)\n");
            fprintf (src, "      break; /* exit for loop */\n");
            fprintf (src, "    }\n");

            fprintf (src, "    elmtLen1 = BDecLen (b, setBytesDecoded, env);\n");
            fprintf (src, "    switch (tag1)\n");
            fprintf (src, "    {\n");
            mandatoryElmtCount = 0;
            FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
            {
                cxxtri =  e->type->cxxTypeRefInfo;

                tags = GetTags (e->type, &stoleChoiceTags);

                if (LIST_EMPTY (tags))
                {
                    fprintf (src, "      // ANY Type ?\n");
                    fprintf (src, "      case MAKE_TAG_ID (?, ?, ?):\n");
                }
                else
                {
                    tag = (Tag*)FIRST_LIST_ELMT (tags);
                    classStr = Class2ClassStr (tag->tclass);
                    codeStr = Code2UnivCodeStr (tag->code);
                    formStr = Form2FormStr (tag->form);

                    if (tag->tclass == UNIV)
                    {
                        if (tag->form == ANY_FORM)
                        {
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
                        }
                        else
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
                    }
                    else
                    {
                        if (tag->form == ANY_FORM)
                        {
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (PRIM), tag->code);
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (CONS), tag->code);
                        }
                        else
                            fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, formStr, tag->code);
                    }

                    /* now decode extra tags/length pairs */
                    AsnListFirst (tags);
                    AsnListNext (tags);
                    elmtLevel = 1;
                    if (stoleChoiceTags)
                    {
                        FOR_REST_LIST_ELMT (tag, tags)
                        {
                            classStr = Class2ClassStr (tag->tclass);
                            codeStr = Code2UnivCodeStr (tag->code);
                            formStr = Form2FormStr (tag->form);

                            if (tag->tclass == UNIV)
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
                                }
                                else
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
                            }
                            else
                            {
                                if (tag->form == ANY_FORM)
                                {
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (PRIM), tag->code);
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, Form2FormStr (CONS), tag->code);
                                }
                                else
                                    fprintf (src, "      case MAKE_TAG_ID (%s, %s, %d):\n", classStr, formStr, tag->code);
                            }
                        }
                    }
                    else /* didn't steal nested choice's tags */
                    {
                        FOR_REST_LIST_ELMT (tag, tags)
                        {
                            classStr = Class2ClassStr (tag->tclass);
                            codeStr = Code2UnivCodeStr (tag->code);
                            formStr = Form2FormStr (tag->form);

                            fprintf (src, "        tag1 = BDecTag (b, setBytesDecoded, env);\n");
                            if (tag->form == ANY_FORM)
                            {
                                if (tag->tclass == UNIV)
                                {
                                    fprintf (src, "        if ((tag1 != MAKE_TAG_ID (%s, %s, %s))\n",  classStr, Form2FormStr (PRIM), codeStr);
                                    fprintf (src, "           && (tag1 != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), codeStr);
                                }
                                else
                                {
                                    fprintf (src, "        if ((tag1 != MAKE_TAG_ID (%s, %s, %d))\n", classStr, Form2FormStr (PRIM), tag->code);
                                    fprintf (src, "           && (tag1 != MAKE_TAG_ID (%s, %s, %d)))\n", classStr, Form2FormStr (CONS), tag->code);
                                }

                            }
                            else
                            {
                                if (tag->tclass == UNIV)
                                    fprintf (src, "        if (tag1 != MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, codeStr);
                                else
                                    fprintf (src, "        if (tag1 != MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
                            }

                            fprintf (src, "        {\n");
                            fprintf (src, "           Asn1Error << \"Unexpected Tag\" << std::endl;\n");
                            fprintf (src, "           longjmp (env, %d);\n", longJmpValG--);
                            fprintf (src, "        }\n\n");

                            fprintf (src, "        elmtLen%d = BDecLen (b, setBytesDecoded, env);\n", ++elmtLevel);
                        }
                    }
                }
                /*
                 * if the choices element is another choice &&
                 * we didn't steal its tags then we must grab
                 * the key tag out of the contained CHOICE
                 */
                if (!stoleChoiceTags && (GetBuiltinType (e->type) == BASICTYPE_CHOICE))
                {
                    fprintf (src, "        tag1 = BDecTag (b, setBytesDecoded, env);\n");
                    fprintf (src, "        elmtLen%d = BDecLen (b, setBytesDecoded, env);\n", ++elmtLevel);
                }

                varName = cxxtri->fieldName;

                /* decode content */
                if (cxxtri->isPtr)
                    fprintf (src, "        %s = new %s;\n", varName, cxxtri->className);

                /* decode content */
                tmpTypeId = GetBuiltinType (e->type);
                if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
                {
                    /*
                     * must check for another EOC for ANYs
                     * since the any decode routines decode
                     * their own first tag/len pair
                     */
                    elmtLevel++;

                    fprintf (src, "        %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");

                    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
                    if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
                    {
                        fprintf (src, "SetTypeByOid (");
                        if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                            fprintf (src, " *");
                        fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                    }
                    else
                    {
                        fprintf (src, "SetTypeByInt (");
                        if (defByNamedType->type->cxxTypeRefInfo->isPtr)
                            fprintf (src, " *");
                        fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
                    }

                    fprintf (src, "        %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "B%s (b, setBytesDecoded, env);\n",  r->decodeBaseName);
                }
                else if (tmpTypeId == BASICTYPE_ANY)
                {
                    /*
                     * must check for another EOC for ANYs
                     * since the any decode routines decode
                     * their own first tag/len pair
                     */
                    elmtLevel++;

                    fprintf (src, "        %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "SetTypeBy???(???);\n");

                    fprintf (src, "        %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");
                    fprintf (src, "B%s (b, setBytesDecoded, env);\n",  r->decodeBaseName);
                }
                else
                {
                    fprintf (src, "        %s", varName);
                    if (cxxtri->isPtr)
                        fprintf (src, "->");
                    else
                        fprintf (src, ".");

                    fprintf (src, "B%s (b, tag1, elmtLen%d, setBytesDecoded, env);\n",  r->decodeContentBaseName, elmtLevel);
                }

                /* decode Eoc (s) */
                for (i = elmtLevel-1; i >= 1; i--)
                {
                    fprintf (src, "          if (elmtLen%d == INDEFINITE_LEN)\n", i);
                    fprintf (src, "            BDecEoc (b, setBytesDecoded, env);\n\n");
                }

                /* keep track of decoded non-optional elmts */
                if (!e->type->optional && (e->type->defaultVal == NULL))
                {
                    mandatoryElmtCount++;
                    fprintf (src, "          mandatoryElmtsDecoded++;\n");
                }
                fprintf (src, "          break;\n\n");

                FreeTags (tags);
            } /* for each elmt */
            fprintf (src, "       default:\n");
            fprintf (src, "         Asn1Error << \"Unexpected Tag on SET elmt.\" << std::endl;\n");
            fprintf (src, "         longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "    } // end switch\n");
            fprintf (src, "  } // end for loop\n");
            fprintf (src, "  bytesDecoded += setBytesDecoded;\n");
            fprintf (src, "  if (mandatoryElmtsDecoded != %d)\n", mandatoryElmtCount);
            fprintf (src, "  {\n");
            fprintf (src, "     Asn1Error << \"ERROR - non-optional SET element missing.\" << std::endl;\n");
            fprintf (src, "     longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

        } /* if not empty set clause */

        fprintf (src, "} // %s::B%s\n\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName);
    }
    /* end of decode content method code */

    /* BerEncode */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);

        fprintf (src, "%s\n", lenTypeNameG);
        fprintf (src, "%s::B%s (%s b)\n", td->cxxTypeDefInfo->className, r->encodeBaseName, bufTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s l;\n", lenTypeNameG);
        fprintf (src, "  l = B%s (b);\n", r->encodeContentBaseName);

        /* encode each tag/len pair if any */
        FOR_EACH_LIST_ELMT_RVS (tag, set->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* set's are constructed */
            tagLen = TagByteLen (tag->code);

            fprintf (src, "  l += BEncConsLen (b, l);\n");

            if (tag->tclass == UNIV)
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %s);\n", tagLen, classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %d);\n", tagLen, classStr, formStr, tag->code);
        }
        fprintf (src, "  return l;\n");
        fprintf (src, "}\n\n");
    }
    /* end of BerEncode */

    /* BerDecode */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s &bytesDecoded, %s env);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s tag;\n", tagTypeNameG);

        /* print extra locals for redundant lengths */
        for (i = 1; (set->tags != NULL) && (i <= LIST_COUNT (set->tags)); i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);
        fprintf (src, "\n");

        /*  decode tag/length pair (s) */
        elmtLevel = 0;
        FOR_EACH_LIST_ELMT (tag, set->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* sets are constructed */

            fprintf (src, "  if ((tag = BDecTag (b, bytesDecoded, env)) != ");

            if (tag->tclass == UNIV)
                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
            fprintf (src, "  {\n");
	    fprintf (src, "    Asn1Error << \"%s::B%s: ERROR - wrong tag\" << std::endl;\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
            fprintf (src, "    longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

            fprintf (src, "  elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
        }

        fprintf (src, "  B%s (b, tag, elmtLen%d, bytesDecoded, env);\n", r->decodeContentBaseName, i-1);

        /* grab any EOCs that match redundant, indef lengths */
        for (i = elmtLevel-1; i > 0; i--)
        {
            fprintf (src, "  if (elmtLen%d == INDEFINITE_LEN)\n", i);
            fprintf (src, "    BDecEoc (b, bytesDecoded, env);\n");
        }

        fprintf (src, "}\n\n");
    }
    /* end of BerDecode */

    PrintPduMemberFcns (src, hdr, r, td->cxxTypeDefInfo->className);

    /* write code for printing */
    if (printPrintersG)
    {
        fprintf (hdr, "  void			Print (std::ostream &os) const;\n");

        fprintf (src, "void %s::Print (std::ostream &os) const\n", td->cxxTypeDefInfo->className);
        fprintf (src, "{\n");
        allOpt = AllElmtsOptional (set->basicType->a.set);
        if (allOpt)
            fprintf (src, "  int nonePrinted = true;\n");

        fprintf (src, "  os << \"{ -- SET --\" << std::endl;\n");
        fprintf (src, "  indentG += stdIndentG;\n\n");

        FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
        {
            inTailOptElmts = IsTailOptional (set->basicType->a.set);

            if (e->type->cxxTypeRefInfo->isPtr)
                fprintf (src, "  if (%s (%s))\n", cxxtri->optTestRoutineName, e->type->cxxTypeRefInfo->fieldName);

	    fprintf (src, "  {\n");

            if (allOpt)
            {
                if (e != FIRST_LIST_ELMT (set->basicType->a.set))
                {
                    fprintf (src, "    if (!nonePrinted)\n");
                    fprintf (src, "      os << \",\" << std::endl;\n");
                }
                fprintf (src, "    nonePrinted = false;\n", i);
            }
            else if (inTailOptElmts) /* cannot be first elmt ow allOpt is true */
                fprintf (src, "    os << \",\"<< std::endl;\n");

            fprintf (src, "    Indent (os, indentG);\n");

            if (e->fieldName != NULL)
                fprintf (src, "    os << \"%s \";\n", e->fieldName);

            if (e->type->cxxTypeRefInfo->isPtr)
                fprintf (src, "    os << *%s;\n", e->type->cxxTypeRefInfo->fieldName);
            else
                fprintf (src, "    os << %s;\n", e->type->cxxTypeRefInfo->fieldName);

            if (e != LAST_LIST_ELMT (set->basicType->a.set) && !inTailOptElmts && !NextIsTailOptional (set->basicType->a.set))
                fprintf (src, "    os << \",\" << std::endl;\n");

	    fprintf (src, "  }\n");

            if (e->type->cxxTypeRefInfo->isPtr)
	    {
		fprintf (src, "  else\n");
#ifdef KHO
		fprintf (src, "    os << \"-- void2 --\\n\";\n");
#else
		fprintf (src, "    os << \"-- void --\";\n");
#endif
	    }

	    fprintf (src, "\n");

            if (e == LAST_LIST_ELMT (set->basicType->a.set))
                fprintf (src, "  os << std::endl;\n");
        }
        fprintf (src, "  indentG -= stdIndentG;\n");
        fprintf (src, "  Indent (os, indentG);\n");
        fprintf (src, "  os << \"}\";\n");
        fprintf (src, "} // %s - operator <<\n\n\n", td->cxxTypeDefInfo->className);
    }
    /* end of print method code */

    /* close class definition */
    fprintf (hdr, "};\n\n\n");

} /* PrintCxxSetDefCode */


/*
 * This major Bogosity results from gcc2.2.2 inability to handle
 * template properly
 */
static void
PrintCxxListClass PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, parent, lst),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *lst)
{
    char *lcn; /* list class name */
    char *ecn; /* (list) elmt class name */
    char *classStr;
    char *formStr;
    int tagLen;
    Tag *tag;
    int i, elmtLevel;

    lcn = td->cxxTypeDefInfo->className;
    ecn = lst->basicType->a.setOf->cxxTypeRefInfo->className;

#ifdef _IBM_ENC_
#include "./ibm_editor/print_cxx_list_class.h"
#endif /* _IBM_ENC_ */

    fprintf (hdr, "class %s%s\n", lcn, baseClassesG);
    fprintf (hdr, "{\n");
    fprintf (hdr, "protected:\n");

    fprintf (hdr, "  unsigned long int	count;\n");
    fprintf (hdr, "  struct AsnListElmt\n");
    fprintf (hdr, "  {\n");
    fprintf (hdr, "    AsnListElmt	*next;\n");
    fprintf (hdr, "    AsnListElmt	*prev;\n");
#ifdef _IBM_ENC_
    fprintf (hdr, "    void		*operator new (size_t t) { return mem_mgr_ptr->Get (t); }    // Guido Grassel 12.8.93\n");
    fprintf (hdr, "    void		operator delete (void *p) { mem_mgr_ptr->Put (p); }	// Guido Grassel 12.8.93\n");
#endif /* _IBM_ENC_ */
    fprintf (hdr, "    %s	*elmt;\n", ecn);
    fprintf (hdr, "  }			*first, *curr, *last;\n\n");

    fprintf (hdr, "public:\n");

#if META
    if (printMetaG)
    {
	const char *emtn = "?";
	switch (lst->basicType->choiceId)
	{
	    case BASICTYPE_SEQUENCEOF:
		emtn = "SEQUENCE_OF";
		break;
	    case BASICTYPE_SETOF:
		emtn = "SET_OF";
		break;
	}

	fprintf (hdr, "#if META\n");
	fprintf (src, "#if META\n\n");

	fprintf (hdr, "  static const AsnListTypeDesc	_desc;\n");
	fprintf (hdr, "  const AsnTypeDesc		*_getdesc() const;\n");
	fprintf (hdr, "  AsnType			*_getref (const char *index, bool create = false);\n\n");

	fprintf (src, "static AsnType *create%s()\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return new %s;\n", td->cxxTypeDefInfo->className);
	fprintf (src, "}\n\n");

	fprintf (src, "const AsnListTypeDesc %s::_desc\n", td->cxxTypeDefInfo->className);
	fprintf (src, "(\n");
	fprintf (src, "  &%sModuleDesc,\n", m->cxxname);
	if (printMetaG == META_backend_names)
	    fprintf (src, "  \"%s\", // `%s'\n", td->cxxTypeDefInfo->className, td->definedName);
	else /* META_asn1_names */
	    fprintf (src, "  \"%s\", // `%s'\n", td->definedName, td->cxxTypeDefInfo->className);
	fprintf (src, "  %s,\n", isMetaPDU (m->modId->name, td->definedName, meta_pdus_G) ? "true" : "false");
	fprintf (src, "  AsnTypeDesc::%s,\n", emtn);
	fprintf (src, "  create%s,\n", td->cxxTypeDefInfo->className);
	fprintf (src, "  &%s::_desc\n", ecn);
	fprintf (src, ");\n\n");

	fprintf (src, "const AsnTypeDesc *%s::_getdesc() const\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  return &_desc;\n");
	fprintf (src, "}\n\n");

	fprintf (src, "AsnType *%s::_getref (const char *strindex, bool create)\n", td->cxxTypeDefInfo->className);
	fprintf (src, "{\n");
	fprintf (src, "  bool insert;\n");
	fprintf (src, "  unsigned long index;\n");
	fprintf (src, "  char c;\n");
	fprintf (src, "  if (sscanf (strindex, \"insert %%lu%%c\", &index, &c) == 1)\n");
	fprintf (src, "  {\n");
	fprintf (src, "    insert = true;\n");
	fprintf (src, "  }\n");
	fprintf (src, "  else if (sscanf (strindex, \"%%lu%%c\", &index, &c) == 1)\n");
	fprintf (src, "  {\n");
	fprintf (src, "    insert = false;\n");
	fprintf (src, "  }\n");
	fprintf (src, "  else\n");
	fprintf (src, "    return NULL;\n");
	fprintf (src, "  if (insert && index == Count())\n");
	fprintf (src, "    return Append();\n");
	fprintf (src, "  if (index >= Count())\n");
	fprintf (src, "    return NULL;\n");
	fprintf (src, "  SetCurrElmt (index);\n");
	fprintf (src, "  return insert ? InsertBefore() : Curr();\n");
	fprintf (src, "}\n\n");

#if TCL
	if (printTclG)
	{
	    fprintf (hdr, "#if TCL\n");
	    fprintf (src, "#if TCL\n\n");

	    fprintf (hdr, "  int			TclGetDesc (Tcl_DString *) const;\n");
	    fprintf (hdr, "  int			TclGetVal (Tcl_Interp *) const;\n");
	    fprintf (hdr, "  int			TclSetVal (Tcl_Interp *, const char *valstr);\n");
	    fprintf (hdr, "  int			TclUnsetVal (Tcl_Interp *, const char *indexstr);\n");

	    fprintf (src, "int %s::TclGetDesc (Tcl_DString *valstr) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  char countstr[80];\n");
	    fprintf (src, "  sprintf (countstr, \"%%lu\", count);\n");
	    fprintf (src, "  Tcl_DStringAppendElement (valstr, countstr);\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "  return _desc.base->AsnTypeDesc::TclGetDesc (valstr);\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclGetVal (Tcl_Interp *interp) const\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Tcl_DString valstr;\n");
	    fprintf (src, "  Tcl_DStringInit (&valstr);\n");
	    fprintf (src, "  //for (SetCurrToFirst(); Curr(); GoNext())\n");
	    fprintf (src, "  for (const AsnListElmt *run=first; run; run=run->next)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    if (run->elmt->TclGetVal (interp) != TCL_OK)\n");
	    fprintf (src, "    {\n");
	    fprintf (src, "      Tcl_DStringFree (&valstr);\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "    }\n");
	    fprintf (src, "    Tcl_DStringAppendElement (&valstr, interp->result);\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  Tcl_ResetResult (interp);\n");
	    fprintf (src, "  Tcl_DStringResult (interp, &valstr);\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclSetVal (Tcl_Interp *interp, const char *valstr)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  Args elem;\n");
	    fprintf (src, "  if (Tcl_SplitList (interp, (char*)valstr, &elem.c, &elem.v) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "\n");
	    fprintf (src, "  while (First())\n");
	    fprintf (src, "    RemoveCurrFromList();\n");
	    fprintf (src, "\n");
	    fprintf (src, "  for (int i=0; i<elem.c; i++)\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    if (Append()->TclSetVal (interp, elem.v[i]) != TCL_OK)\n");
	    fprintf (src, "      return TCL_ERROR;\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (src, "int %s::TclUnsetVal (Tcl_Interp *interp, const char *indexstr)\n", td->cxxTypeDefInfo->className);
	    fprintf (src, "{\n");
	    fprintf (src, "  int index;\n");
	    fprintf (src, "  if (Tcl_GetInt (interp, (char*)indexstr, &index) != TCL_OK)\n");
	    fprintf (src, "    return TCL_ERROR;\n");
	    fprintf (src, "  if (index >= Count())\n");
	    fprintf (src, "  {\n");
	    fprintf (src, "    sprintf (interp->result, \"error: list: index %%d out of range (0-%%d)\", index, Count()-1);\n");
	    fprintf (src, "    return NULL;\n");
	    fprintf (src, "  }\n");
	    fprintf (src, "  SetCurrElmt (index);\n");
	    fprintf (src, "  RemoveCurrFromList();\n");
	    fprintf (src, "  return TCL_OK;\n");
	    fprintf (src, "}\n\n");

	    fprintf (hdr, "#endif // TCL\n");
	    fprintf (src, "#endif // TCL\n\n");
	}
#endif /* TCL */

	fprintf (hdr, "#endif // META\n\n");
	fprintf (src, "#endif // META\n\n");
    }
#endif /* META */


    fprintf (hdr, "			%s() { count = 0; first = curr = last = NULL; }\n", lcn);

    fprintf (hdr, "			%s (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (hdr, "			~%s();\n", td->cxxTypeDefInfo->className);

    /* print clone routine for ANY mgmt */
    PrintCloneMethod (hdr, src, td);

    fprintf (hdr, "  %s		&operator = (const %s &);\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);

    fprintf (hdr, "  void		SetCurrElmt (unsigned long int index);\n");
    fprintf (hdr, "  unsigned long int	GetCurrElmtIndex();\n");
    fprintf (hdr, "  void		SetCurrToFirst() { curr = first; }\n");
    fprintf (hdr, "  void		SetCurrToLast()  { curr = last; }\n");

    fprintf (hdr, "  // reading member fcns\n");
    fprintf (hdr, "  int			Count() const	{ return count; }\n");
    fprintf (hdr, "  // NOTE: if your compiler complains about these NULLs, its definition of NULL is broken (and you better change it there!)\n");
    fprintf (hdr, "  %s	*First() const	{ return count > 0 ? first->elmt : NULL; }\n", ecn);
    fprintf (hdr, "  %s	*Last() const	{ return count > 0 ? last->elmt : NULL; }\n", ecn);
    fprintf (hdr, "  %s	*Curr() const	{ return curr ? curr->elmt : NULL; }\n", ecn);
    fprintf (hdr, "  %s	*Next() const	{ return curr && curr->next ? curr->next->elmt : NULL; }\n", ecn);
    fprintf (hdr, "  %s	*Prev() const	{ return curr && curr->prev ? curr->prev->elmt : NULL; }\n\n", ecn);

    fprintf (hdr, "  // routines that move the curr elmt\n");
    fprintf (hdr, "  %s	*GoNext() { if (curr) curr = curr->next; return Curr(); }\n", ecn);
    fprintf (hdr, "  %s	*GoPrev() { if (curr) curr = curr->prev; return Curr(); }\n\n", ecn);

    fprintf (hdr, "  // write & alloc fcns - returns new elmt\n");
    fprintf (hdr, "  %s	*Append();  // add elmt to end of list\n", ecn);
    fprintf (hdr, "  %s	*Prepend(); // add elmt to beginning of list\n", ecn);
    fprintf (hdr, "  %s	*InsertBefore(); //insert elmt before current elmt\n", ecn);
    fprintf (hdr, "  %s	*InsertAfter(); //insert elmt after current elmt\n\n", ecn);

    fprintf (hdr, "  // write & alloc & copy - returns list after copying elmt\n");
    fprintf (hdr, "  %s	&AppendCopy (%s &elmt);  // add elmt to end of list\n", lcn, ecn);
    fprintf (hdr, "  %s	&PrependCopy (%s &elmt); // add elmt to beginning of list\n", lcn, ecn);
    fprintf (hdr, "  %s	&InsertBeforeAndCopy (%s &elmt); //insert elmt before current elmt\n", lcn, ecn);
    fprintf (hdr, "  %s	&InsertAfterAndCopy (%s &elmt); //insert elmt after current elmt\n\n", lcn, ecn);

    fprintf (hdr, "  // removing the current elmt from the list\n");
    fprintf (hdr, "  void		RemoveCurrFromList();\n\n");

    fprintf (hdr, "  // encode and decode routines    \n");

    /* print PDU oriented encode routine */
    if (printEncodersG)
    {
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);

        fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName, bufTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s l;\n", lenTypeNameG);

        /* encode the list content */
        fprintf (src, "  l = B%s (b);\n", r->encodeContentBaseName);

        /* encode each tag/len pair if any */
        FOR_EACH_LIST_ELMT_RVS (tag, lst->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* choices are constructed */
            tagLen = TagByteLen (tag->code);

            /* always constructed lengths for list */
            fprintf (src, "  l += BEncConsLen (b, l);\n");

            if (tag->tclass == UNIV)
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %s);\n", tagLen, classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "  l += BEncTag%d (b, %s, %s, %d);\n", tagLen, classStr, formStr, tag->code);
        }
        fprintf (src, "  return l;\n");
        fprintf (src, "}\n\n");
    }
    /* end of ber encode function */

    /* do BerDecode function */
    if (printDecodersG)
    {
        fprintf (hdr, "  void			B%s (%s b, %s &bytesDecoded, %s env);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG, envTypeNameG);

        fprintf (src, "void %s::B%s (%s b, %s &bytesDecoded, %s env)\n", td->cxxTypeDefInfo->className, r->decodeBaseName,  bufTypeNameG, lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "  %s tag;\n", tagTypeNameG);

        /* print extra locals for redundant lengths */
        for (i = 1; (lst->tags != NULL) && (i <= LIST_COUNT (lst->tags)); i++)
            fprintf (src, "  %s elmtLen%d;\n", lenTypeNameG, i);
        fprintf (src, "\n");

        /*  decode tag/length pair (s) */
        elmtLevel = 0;
        FOR_EACH_LIST_ELMT (tag, lst->tags)
        {
            classStr = Class2ClassStr (tag->tclass);
            formStr = Form2FormStr (CONS);  /* lists are constructed */

            fprintf (src, "  if ((tag = BDecTag (b, bytesDecoded, env)) != ");

            if (tag->tclass == UNIV)
                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, Code2UnivCodeStr (tag->code));
            else
                fprintf (src, "MAKE_TAG_ID (%s, %s, %d))\n", classStr, formStr, tag->code);
            fprintf (src, "  {\n");
	    fprintf (src, "    Asn1Error << \"%s::B%s: ERROR - wrong tag\" << std::endl;\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
            fprintf (src, "    longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "  }\n");

            fprintf (src, "  elmtLen%d = BDecLen (b, bytesDecoded, env);\n", ++elmtLevel);
        }

        fprintf (src, "  B%s (b, tag, elmtLen%d, bytesDecoded, env);\n", r->decodeContentBaseName, elmtLevel);

        /* grab any EOCs that match redundant, indef lengths */
        for (i = elmtLevel-1; i > 0; i--)
        {
            fprintf (src, "  if (elmtLen%d == INDEFINITE_LEN)\n", i);
            fprintf (src, "     BDecEoc (b, bytesDecoded, env);\n");
        }

        fprintf (src, "}\n\n");
    }
    /* end of BDec function */


    if (printEncodersG)
        fprintf (hdr, "  %s		B%s (%s b);\n", lenTypeNameG, r->encodeContentBaseName, bufTypeNameG);

    if (printDecodersG)
        fprintf (hdr, "  void			B%s (%s b, %s tag, %s elmtLen, %s &bytesDecoded, %s env);\n\n", r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG, envTypeNameG);

    fprintf (hdr, "  PDU_MEMBER_MACROS\n");

    if (printPrintersG)
        fprintf (hdr, "  void		Print (std::ostream &os) const;\n");

    fprintf (hdr, "};\n\n\n");

} /* PrintCxxListClass */


/*
 * Prints code to decode and check tags and lengths for a
 * SEQ OF/SET OF element.
 *
 * as usual, assumes:
 *  b for buf var name
 *  elmtLen for elmts len var name
 *  env for environment var name
 *  listBytesDecoded for the runing total bytes decoded
 *  tag1 for tag
 *
 *  Assumes first tag has been decoded and is in 'tag1' var
 */
static void
PrintCxxListTagAndLenDecCode PARAMS ((src, td, t),
    FILE *src _AND_
    TypeDef *td _AND_
    Type *t)
{
    TagList *tags;
    Tag *tag;
    int elmtLevel;
    int stoleChoiceTags;

    elmtLevel = 0;

    tags = GetTags (t, &stoleChoiceTags);
    if (stoleChoiceTags)
    {
        fprintf (src, "        if (!(");
        FOR_EACH_LIST_ELMT (tag, tags)
        {
            fprintf (src, "(tag1 == ");
            PrintMakeTag (src, tag);
            if (tag->form == ANY_FORM)
            {
                fprintf (src, ")\n            || (tag1 == ");
                tag->form = CONS;
                PrintMakeTag (src, tag);
                fprintf (src, ")\n");
            }
            else
                fprintf (src, ")");

            if (tag != (Tag *)LAST_LIST_ELMT (tags))
                fprintf (src, "\n         || ");
        }
        fprintf (src, "))\n");
        fprintf (src, "        {\n");
        fprintf (src, "            Asn1Error << \"Unexpected Tag\" << std::endl;\n");
        fprintf (src, "            longjmp (env, %d);\n", longJmpValG--);
        fprintf (src, "        }\n\n");
        fprintf (src, "        elmtLen%d = BDecLen (b, listBytesDecoded, env);\n", ++elmtLevel);
    }

    else /* didn't steal nested choice's tags */
    {
        AsnListFirst (tags);

        FOR_EACH_LIST_ELMT (tag, tags)
        {

            fprintf (src, "        if ((tag1 != ");
            PrintMakeTag (src, tag);
            if (tag->form == ANY_FORM)
            {
                fprintf (src, ")\n         && (tag1 != ");
                tag->form = CONS;
                PrintMakeTag (src, tag);
                fprintf (src, "))\n");
            }
            else
                fprintf (src, "))\n");

            fprintf (src, "        {\n");
            fprintf (src, "            Asn1Error << \"Unexpected Tag\" << std::endl;\n");
            fprintf (src, "            longjmp (env, %d);\n", longJmpValG--);
            fprintf (src, "        }\n\n");
            fprintf (src, "        elmtLen%d = BDecLen (b, listBytesDecoded, env);\n", ++elmtLevel);

            if (tag != (Tag*)LAST_LIST_ELMT (tags))
                fprintf (src, "        tag1 = BDecTag (b, listBytesDecoded, env);\n\n");

        }

        /*
         * if this seq element is CHOICE &&
         * we didn't steal its tags then we must grab
         * the key tag out of the contained CHOICE
         */
        if (GetBuiltinType (t) == BASICTYPE_CHOICE)
        {
            fprintf (src, "        tag1 = BDecTag (b, listBytesDecoded, env);\n");
            fprintf (src, "        elmtLen%d = BDecLen (b, listBytesDecoded, env);\n", ++elmtLevel);
        }
    }
    FreeTags (tags);
} /* PrintCxxListTagAndLenDecCode */

/*
 * This major Bogosity results from gcc2.2.2 inability to handle
 * templates properly
 */
static void
PrintCxxListMethods PARAMS ((src, hdr, mods, m, r, td, parent, lst, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *lst _AND_
    int novolatilefuncs)
{
    char *lcn; /* list class name */
    char *ecn; /* (list) elmt class name */
    int elmtLevel;
    int i;
    enum BasicTypeChoiceId tmpTypeId;
    Tag *tag;
    char *classStr;
    char *formStr;
    int tagLen;

    lcn = td->cxxTypeDefInfo->className;
    ecn = lst->basicType->a.setOf->cxxTypeRefInfo->className;

    fprintf (src, "%s::%s (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s::%s (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "}\n\n");

    fprintf (src, "%s::~%s()\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "{\n");
    fprintf (src, "  SetCurrToFirst();\n");
    fprintf (src, "  for (; Curr() != NULL; RemoveCurrFromList())\n");
    fprintf (src, "    ;\n");
    fprintf (src, "} // end of destructor\n\n");

    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &that)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "%s &%s::operator = (const %s &)\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "{\n");
    fprintf (src, "#if SNACC_DEEP_COPY\n");
    fprintf (src, "  if (this != &that)\n");
    fprintf (src, "  {\n");
    fprintf (src, "    SetCurrToFirst();\n");
    fprintf (src, "    for (; Curr(); RemoveCurrFromList())\n");
    fprintf (src, "      ;\n");
    fprintf (src, "\n");
    fprintf (src, "    //that.SetCurrToFirst();\n");
    fprintf (src, "    //for (; that.Curr(); that.GoNext())\n");
    fprintf (src, "    //  AppendCopy (*that.Curr());\n");
    fprintf (src, "    for (const AsnListElmt *run=that.first; run; run=run->next)\n");
    fprintf (src, "      AppendCopy (*run->elmt);\n");
    fprintf (src, "  }\n");
    fprintf (src, "\n");
    fprintf (src, "  return *this;\n");
    fprintf (src, "#else // SNACC_DEEP_COPY\n");
    fprintf (src, "  Asn1Error << \"use of incompletely defined %s &%s::operator = (const %s &)\" << std::endl;\n", td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className, td->cxxTypeDefInfo->className);
    fprintf (src, "  abort();\n");
    fprintf (src, "  // if your compiler complains here, check the -novolat option\n");
    if (novolatilefuncs)
    {
      fprintf (src, "  return *this;\n");
    }
    fprintf (src, "#endif // SNACC_DEEP_COPY\n");
    fprintf (src, "}\n\n");

    if (printPrintersG)
    {
        fprintf (src, "void %s::Print (std::ostream &os) const\n", td->cxxTypeDefInfo->className);
        fprintf (src, "{\n");
        fprintf (src, "    os << \"{ -- SEQUENCE/SET OF -- \" << std::endl;\n");
        fprintf (src, "    indentG += stdIndentG;\n");

        fprintf (src, "    //SetCurrToFirst();\n");
        fprintf (src, "    //for (; Curr() != NULL; GoNext())\n");
        fprintf (src, "    for (const AsnListElmt *run=first; run; run=run->next)\n");
        fprintf (src, "    {\n");
        fprintf (src, "        Indent (os, indentG);\n");
        fprintf (src, "        //os << *Curr();\n");
        fprintf (src, "        os << *run->elmt;\n");
        fprintf (src, "        //if (Curr() != Last())\n");
        fprintf (src, "        if (run != last)\n");
        fprintf (src, "            os << \",\";\n");
        fprintf (src, "        os << std::endl;\n");
        fprintf (src, "    }\n");

        fprintf (src, "    indentG -= stdIndentG;\n");
        fprintf (src, "    Indent (os, indentG);\n");
#ifdef KHO
        fprintf (src, "    os << \"}\\n\";\n");
#else
        fprintf (src, "    os << \"}\";\n");
#endif

        fprintf (src, "} // Print\n\n\n");
    }

    fprintf (src, "void  %s::SetCurrElmt (unsigned long int index)\n", lcn);
    fprintf (src, "{\n");
    fprintf (src, "  unsigned long int i;\n");
    fprintf (src, "  curr = first;\n");
    fprintf (src, "  if (count)\n");
    fprintf (src, "    for (i = 0; (i < (count-1)) && (i < index); i++)\n");
    fprintf (src, "      curr = curr->next;\n");
    fprintf (src, "} // %s::SetCurrElmt\n\n\n", lcn);


    fprintf (src, "unsigned long int  %s::GetCurrElmtIndex()\n", lcn);
    fprintf (src, "{\n");
    fprintf (src, "    unsigned long int i;\n");
    fprintf (src, "    AsnListElmt *tmp;\n");
    fprintf (src, "    if (curr != NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        for (i = 0, tmp = first; tmp != NULL; i++)\n");
    fprintf (src, "        {\n");
    fprintf (src, "            if (tmp == curr)\n");
    fprintf (src, "                return i;\n");
    fprintf (src, "            else\n");
    fprintf (src, "                tmp = tmp->next;\n");
    fprintf (src, "        }\n");
    fprintf (src, "    }\n");
    fprintf (src, "    return count;\n");
    fprintf (src, "} // %s::GetCurrElmtIndex\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, put at end of list\n");
    fprintf (src, "//  and return the component type\n");
    fprintf (src, "%s *%s::Append()\n", ecn, lcn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt  = new %s;\n", ecn);
    fprintf (src, "    newElmt->next = NULL;\n");
    fprintf (src, "    if (last == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = NULL;\n");
    fprintf (src, "        first = last  = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = last;\n");
    fprintf (src, "        last->next    = newElmt;\n");
    fprintf (src, "        last          = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return (curr = newElmt)->elmt;\n");
    fprintf (src, "} // %s::Append\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, put at beginning of list\n");
    fprintf (src, "//  and return the component type\n");
    fprintf (src, "%s  *%s::Prepend()\n", ecn, lcn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    newElmt->prev = NULL;\n");
    fprintf (src, "    if (first == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = NULL;\n");
    fprintf (src, "        first = last  = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = first;\n");
    fprintf (src, "        first->prev   = newElmt;\n");
    fprintf (src, "        first         = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return (curr = newElmt)->elmt;\n");
    fprintf (src, "} // %s::Prepend\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, insert it before the\n");
    fprintf (src, "// current element and return the component type\n");
    fprintf (src, "// if the current element is null, the new element\n");
    fprintf (src, "// is placed at the beginning of the list.\n");
    fprintf (src, "%s  *%s::InsertBefore()\n", ecn, lcn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    if (curr == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = first;\n");
    fprintf (src, "        newElmt->prev = NULL;\n");
    fprintf (src, "        first = newElmt;\n");
    fprintf (src, "        if (last == NULL)\n");
    fprintf (src, "            last = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = curr;\n");
    fprintf (src, "        newElmt->prev = curr->prev;\n");
    fprintf (src, "        curr->prev = newElmt;\n");
    fprintf (src, "        if (curr == first)\n");
    fprintf (src, "            first = newElmt;\n");
    fprintf (src, "        else\n");
    fprintf (src, "            newElmt->prev->next = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return (curr = newElmt)->elmt;\n");
    fprintf (src, "} // %s::InsertBefore\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, insert it after the\n");
    fprintf (src, "// current element and return the component type\n");
    fprintf (src, "// if the current element is null, the new element\n");
    fprintf (src, "// is placed at the end of the list.\n");
    fprintf (src, "%s *%s::InsertAfter()\n", ecn, lcn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    if (curr == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = last;\n");
    fprintf (src, "        newElmt->next = NULL;\n");
    fprintf (src, "        last = newElmt;\n");
    fprintf (src, "        if (first == NULL)\n");
    fprintf (src, "            first = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = curr;\n");
    fprintf (src, "        newElmt->next = curr->next;\n");
    fprintf (src, "        curr->next = newElmt;\n");
    fprintf (src, "        if (curr == last)\n");
    fprintf (src, "            last = newElmt;\n");
    fprintf (src, "        else\n");
    fprintf (src, "            newElmt->next->prev = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return (curr = newElmt)->elmt;\n");
    fprintf (src, "} // %s::InsertAfter\n\n\n", lcn);


    fprintf (src, "%s  &%s::AppendCopy (%s &elmt)\n", lcn, lcn, ecn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    *newElmt->elmt = elmt;\n");
    fprintf (src, "    newElmt->next = NULL;\n");
    fprintf (src, "    if (last == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = NULL;\n");
    fprintf (src, "        first = last  = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = last;\n");
    fprintf (src, "        last->next    = newElmt;\n");
    fprintf (src, "        last          = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return *this;\n");
    fprintf (src, "} // AppendCopy\n\n\n");


    fprintf (src, "%s  &%s::PrependCopy (%s &elmt)\n", lcn, lcn, ecn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    *newElmt->elmt = elmt;\n");
    fprintf (src, "    newElmt->prev = NULL;\n");
    fprintf (src, "    if (first == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = NULL;\n");
    fprintf (src, "        first = last  = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = first;\n");
    fprintf (src, "        first->prev   = newElmt;\n");
    fprintf (src, "        first         = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return *this;\n");
    fprintf (src, "} // %s::PrependCopy\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, insert it before the\n");
    fprintf (src, "// current element, copy the given elmt into the new elmt\n");
    fprintf (src, "// and return the component type.\n");
    fprintf (src, "// if the current element is null, the new element\n");
    fprintf (src, "// is placed at the beginning of the list.\n");
    fprintf (src, "%s &%s::InsertBeforeAndCopy (%s &elmt)\n", lcn, lcn, ecn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    *newElmt->elmt = elmt;\n");
    fprintf (src, "\n");
    fprintf (src, "    if (curr == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = first;\n");
    fprintf (src, "        newElmt->prev = NULL;\n");
    fprintf (src, "        first = newElmt;\n");
    fprintf (src, "        if (last == NULL)\n");
    fprintf (src, "            last = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->next = curr;\n");
    fprintf (src, "        newElmt->prev = curr->prev;\n");
    fprintf (src, "        curr->prev = newElmt;\n");
    fprintf (src, "        if (curr == first)\n");
    fprintf (src, "            first = newElmt;\n");
    fprintf (src, "        else\n");
    fprintf (src, "            newElmt->prev->next = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return *this;\n");
    fprintf (src, "} // %s::InsertBeforeAndCopy\n\n\n", lcn);


    fprintf (src, "// alloc new list elmt, insert it after the\n");
    fprintf (src, "// current element, copy given elmt in to new elmt\n");
    fprintf (src, "//  and return the component type\n");
    fprintf (src, "// if the current element is null, the new element\n");
    fprintf (src, "// is placed at the end of the list.\n");
    fprintf (src, "%s  &%s::InsertAfterAndCopy (%s &elmt)\n", lcn, lcn, ecn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *newElmt;\n");
    fprintf (src, "\n");
    fprintf (src, "    newElmt  = new AsnListElmt;\n");
    fprintf (src, "    newElmt->elmt = new %s;\n", ecn);
    fprintf (src, "    *newElmt->elmt = elmt;\n");
    fprintf (src, "    if (curr == NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = last;\n");
    fprintf (src, "        newElmt->next = NULL;\n");
    fprintf (src, "        last = newElmt;\n");
    fprintf (src, "        if (first == NULL)\n");
    fprintf (src, "            first = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    else\n");
    fprintf (src, "    {\n");
    fprintf (src, "        newElmt->prev = curr;\n");
    fprintf (src, "        newElmt->next = curr->next;\n");
    fprintf (src, "        curr->next = newElmt;\n");
    fprintf (src, "        if (curr == last)\n");
    fprintf (src, "            last = newElmt;\n");
    fprintf (src, "        else\n");
    fprintf (src, "            newElmt->next->prev = newElmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "    count++;\n");
    fprintf (src, "    return *this;\n");
    fprintf (src, "} // %s::InsertAfterAndCopy\n\n\n", lcn);


    fprintf (src, "// remove current element from list if current element is not NULL \n");
    fprintf (src, "// The new current element will be the next element.\n");
    fprintf (src, "// If the current element is the last element in the list\n");
    fprintf (src, "// the second but last element will become the new current element.\n");
    fprintf (src, "void %s::RemoveCurrFromList()\n", lcn);
    fprintf (src, "{\n");
    fprintf (src, "    AsnListElmt *del_elmt;\n");
    fprintf (src, "\n");
    fprintf (src, "    if (curr != NULL)\n");
    fprintf (src, "    {\n");
    fprintf (src, "        del_elmt = curr;\n");
    fprintf (src, "        count--;\n");
    fprintf (src, "\n");
    fprintf (src, "        if (count == 0)\n");
    fprintf (src, "            first = last = curr = NULL;\n");
    fprintf (src, "        else if (curr == first)\n");
    fprintf (src, "        {\n");
    fprintf (src, "            curr = first= first->next;\n");
    fprintf (src, "            first->prev = NULL;\n");
    fprintf (src, "        }\n");
    fprintf (src, "        else if (curr == last)\n");
    fprintf (src, "        {\n");
    fprintf (src, "            curr = last = last->prev;\n");
    fprintf (src, "            last->next = NULL;\n");
    fprintf (src, "        }\n");
    fprintf (src, "        else\n");
    fprintf (src, "        {\n");
    fprintf (src, "            curr->prev->next = curr->next;\n");
    fprintf (src, "            curr->next->prev = curr->prev;\n");
    fprintf (src, "        }\n");
    fprintf (src, "\n");
    fprintf (src, "        delete del_elmt->elmt;\n");
    fprintf (src, "        delete del_elmt;\n");
    fprintf (src, "    }\n");
    fprintf (src, "}\n\n\n");

    if (printEncodersG)
    {
        fprintf (src, "%s %s::B%s (%s b)\n", lenTypeNameG, lcn, r->encodeContentBaseName, bufTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "    AsnListElmt *currElmt;\n");
        fprintf (src, "    %s elmtLen;\n", lenTypeNameG);
        fprintf (src, "    %s totalLen = 0;\n", lenTypeNameG);

        fprintf (src, "    for (currElmt = last; currElmt != NULL; currElmt = currElmt->prev)\n");
        fprintf (src, "    {\n");
        /* encode Eoc (s) if nec */
        PrintCxxEocEncoders (src, td, lst->basicType->a.setOf, "b");

        tmpTypeId = GetBuiltinType (lst->basicType->a.setOf);
        /* list element types cannot by ANY DEFINED BY */
        if (tmpTypeId == BASICTYPE_ANY)
        {
            fprintf (src, "        currElmt->elmt->SetTypeBy???(???);\n");
            fprintf (src, "        elmtLen = currElmt->elmt->B%s (b);\n", r->encodeBaseName);
        }
        else
        {
            fprintf (src, "        elmtLen = currElmt->elmt->B%s (b);\n", r->encodeContentBaseName);
        }

        /* encode list elmt tag/len pairs here */
        PrintCxxTagAndLenEncodingCode (src, td, lst->basicType->a.setOf, "elmtLen", "b");

        fprintf (src, "        totalLen += elmtLen;\n");
        fprintf (src, "    }\n");

        fprintf (src, "    return totalLen;\n");
        fprintf (src, "} // %s::B%s\n\n\n", lcn, r->encodeContentBaseName);
    }

    if (printDecodersG)
    {
        fprintf (src, "void  %s::B%s (%s b, %s /*tag0*/, %s elmtLen0,\n", lcn, r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG);
        fprintf (src, "                                  %s &bytesDecoded, %s env)\n", lenTypeNameG, envTypeNameG);
        fprintf (src, "{\n");
        fprintf (src, "    %s *listElmt;\n", ecn);
        fprintf (src, "    %s tag1;\n", tagTypeNameG);
        fprintf (src, "    %s listBytesDecoded = 0;\n", lenTypeNameG);

        /* print local vars elmtLen for decoding list component */
        elmtLevel = CxxCountVariableLevels (lst->basicType->a.setOf);

        for (i = 1; i <= elmtLevel; i++)
            fprintf (src, "    %s elmtLen%d;\n", lenTypeNameG, i);

        fprintf (src, "\n");


        fprintf (src, "    while ((listBytesDecoded < elmtLen0) || (elmtLen0 == INDEFINITE_LEN))\n");
        fprintf (src, "    {\n");
        fprintf (src, "        tag1 = BDecTag (b, listBytesDecoded, env);\n");

        fprintf (src, "        if ((tag1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))\n");
        fprintf (src, "        {\n");
        fprintf (src, "            BDEC_2ND_EOC_OCTET (b, listBytesDecoded, env);\n");
        fprintf (src, "            break;\n");
        fprintf (src, "        }\n");

        PrintCxxListTagAndLenDecCode (src, td, lst->basicType->a.setOf);

        fprintf (src, "        listElmt = Append();\n");

        /* decode content */
        tmpTypeId = GetBuiltinType (lst->basicType->a.setOf);
        /* note: cannot be ANY DEFINED BY as SET OF/SEQ OF ELMT */
        if (tmpTypeId == BASICTYPE_ANY)
        {
            fprintf (src, "        listElmt->SetTypeBy???(???);\n");

            fprintf (src, "        listElmt->B%s (b, listBytesDecoded, env);\n", r->decodeBaseName, elmtLevel);
        }
        else
            fprintf (src, "        listElmt->B%s (b, tag1, elmtLen%d, listBytesDecoded, env);\n", r->decodeContentBaseName, elmtLevel);

        /* grab any EOCs that match redundant, indef lengths */
        for (i = elmtLevel-1; i > 0; i--)
        {
            fprintf (src, "        if (elmtLen%d == INDEFINITE_LEN)\n", i);
            fprintf (src, "            BDecEoc (b, listBytesDecoded, env);\n");
        }


        fprintf (src, "    }\n\n"); /* end of while */

        fprintf (src, "    bytesDecoded += listBytesDecoded;\n");

        fprintf (src, "} // %s::B%s\n\n\n", lcn, r->decodeContentBaseName);
    }

} /* PrintCxxListMethods */

static void
PrintCxxSetOfDefCode PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, parent, setOf, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *setOf _AND_
    int novolatilefuncs)
{
    /* do class */
    PrintCxxListClass (src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, parent, setOf);

    /* do methods */
    PrintCxxListMethods (src, hdr, mods, m, r, td, parent, setOf, novolatilefuncs);

} /* PrintCxxSetOfDefCode */


static void
PrintCxxAnyDefCode PARAMS ((src, hdr, mods, m, r, td, parent, any),
    FILE *src _AND_
    FILE *hdr _AND_
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    Type *parent _AND_
    Type *any)
{
    fprintf (hdr, "/* ");
    SpecialPrintType (hdr, td, td->type);
    fprintf (hdr, " */\n");
    fprintf (hdr, "typedef %s %s;\n\n", td->type->cxxTypeRefInfo->className, td->cxxTypeDefInfo->className);
} /* PrintCxxAnyDefCode */


static void
PrintCxxTypeDefCode PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    TypeDef *td _AND_
    int novolatilefuncs)
{
    CNamedElmt *n;

    switch (td->type->basicType->choiceId)
    {
        case BASICTYPE_BOOLEAN:  /* library type */
        case BASICTYPE_REAL:  /* library type */
        case BASICTYPE_OCTETSTRING:  /* library type */
        case BASICTYPE_NULL:  /* library type */
        case BASICTYPE_OID:  /* library type */
        case BASICTYPE_INTEGER:  /* library type */
        case BASICTYPE_BITSTRING:  /* library type */
        case BASICTYPE_ENUMERATED:  /* library type */
            PrintCxxSimpleDef (hdr, src, if_IBM_ENC (hdrdb COMMA srcdb COMMA) if_META (m COMMA) r, td);
            break;

        case BASICTYPE_SEQUENCEOF:  /* list types */
        case BASICTYPE_SETOF:
            PrintCxxSetOfDefCode (src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, NULL, td->type, novolatilefuncs);
            break;

        case BASICTYPE_IMPORTTYPEREF:  /* type references */
        case BASICTYPE_LOCALTYPEREF:
            /*
             * if this type has been re-tagged then
             * must create new class instead of using a typedef
             */
            PrintCxxSimpleDef (hdr, src, if_IBM_ENC (hdrdb COMMA srcdb COMMA) if_META (m COMMA) r, td);
            break;

        case BASICTYPE_ANYDEFINEDBY:  /* ANY types */
        case BASICTYPE_ANY:
/*
            fprintf (stderr, "  ANY types require modification. ");
            fprintf (stderr, "  The source files will have a \" ANY - Fix Me! \" comment before related code.\n\n");
*/
            PrintCxxAnyDefCode (src, hdr, mods, m, r, td, NULL, td->type);
            break;

        case BASICTYPE_CHOICE:
            PrintCxxChoiceDefCode (src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, NULL, td->type, novolatilefuncs);
            break;

        case BASICTYPE_SET:
            PrintCxxSetDefCode (src, hdr, mods, m, r, td, NULL, td->type, novolatilefuncs);
            break;

        case BASICTYPE_SEQUENCE:
            PrintCxxSeqDefCode (src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, NULL, td->type, novolatilefuncs);
            break;

        case BASICTYPE_COMPONENTSOF:
        case BASICTYPE_SELECTION:
        case BASICTYPE_UNKNOWN:
        case BASICTYPE_MACRODEF:
        case BASICTYPE_MACROTYPE:
            /* do nothing */
            break;
    }
} /* PrintCxxTypeDefCode */

void
PrintCxxCode PARAMS ((src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) if_META (printMeta COMMA meta COMMA meta_pdus COMMA) mods, m, r, longJmpVal, printTypes, printValues, printEncoders, printDecoders, printPrinters, printFree if_TCL (COMMA printTcl), novolatilefuncs),
    FILE *src _AND_
    FILE *hdr _AND_
    if_IBM_ENC (FILE *srcdb _AND_)
    if_IBM_ENC (FILE *hdrdb _AND_)
    if_META (MetaNameStyle printMeta _AND_)
    if_META (const Meta *meta _AND_)
    if_META (MetaPDU *meta_pdus _AND_)
    ModuleList *mods _AND_
    Module *m _AND_
    CxxRules *r _AND_
    long int longJmpVal _AND_
    int printTypes _AND_
    int printValues _AND_
    int printEncoders _AND_
    int printDecoders _AND_
    int printPrinters _AND_
    int printFree
    if_TCL (_AND_ int printTcl) _AND_
    int novolatilefuncs)
{
    TypeDef *td;
    ValueDef *vd;
#ifdef _IBM_ENC_
    char mm_name[40];
#endif /* _IBM_ENC_ */

    longJmpValG = longJmpVal;
    printTypesG = printTypes;
    printEncodersG = printEncoders;
    printDecodersG = printDecoders;
    printPrintersG = printPrinters;
    printFreeG = printFree;
#if META
    printMetaG = printMeta;
    meta_pdus_G = meta_pdus;
#if TCL
    printTclG = printTcl;
#endif /* TCL */
#endif /* META */

    PrintSrcComment (src, m);
    PrintHdrComment (hdr, m);
#ifdef _IBM_ENC_
    PrintSrcComment (srcdb, m);   /* 20.8.93 IBM-ENC */
    PrintHdrComment (hdrdb, m);   /* 20.8.93 IBM-ENC */

    strcpy (mm_name, m->cxxHdrFileName);
#endif /* _IBM_ENC_ */

    PrintConditionalIncludeOpen (hdr, m->cxxHdrFileName);

#ifdef _IBM_ENC_
    mm_name[strlen (mm_name)-2]='\0';
    fprintf (hdrdb, "#ifndef _%sdb_h_\n", mm_name);
    fprintf(hdrdb, "#define _%sdb_h_\n", mm_name);
#endif /* _IBM_ENC_ */

#if META
    if (printMetaG)
    {
	fprintf (src, "\n");
	fprintf (src, "#ifndef META\n");
	fprintf (src, "#define META	1\n");
	fprintf (src, "#endif\n");
#if TCL
	if (printTclG)
	{
	    fprintf (src, "#ifndef TCL\n");
	    fprintf (src, "#define TCL	META\n");
	    fprintf (src, "#endif\n");
	}
#endif /* TCL */
    }
#endif /* META */

    fprintf (src, "\n");

    PrintSrcIncludes (src, if_IBM_ENC (srcdb COMMA) mods, m);

    fprintf (src, "\n");

    fprintf (hdr, "//------------------------------------------------------------------------------\n");
    fprintf (hdr, "// class declarations:\n\n");
    FOR_EACH_LIST_ELMT (td, m->typeDefs)
        PrintTypeDecl (hdr, td);
    fprintf (hdr, "\n");

#if META
    if (printMeta)
    {
	fprintf (hdr, "#if META\n");
	fprintf (src, "#if META\n\n");

	fprintf (hdr, "//------------------------------------------------------------------------------\n");
	fprintf (hdr, "extern const AsnModuleDesc %sModuleDesc;\n", m->cxxname);

	fprintf (src, "//------------------------------------------------------------------------------\n");
	fprintf (src, "static const AsnTypeDesc *%sModuleTypes[] =\n", m->cxxname);
	fprintf (src, "{\n");
	FOR_EACH_LIST_ELMT (td, m->typeDefs)
	    fprintf (src, "  &%s::_desc,\n", td->cxxTypeDefInfo->className);
	fprintf (src, "  NULL\n");
	fprintf (src, "};\n\n");
#if 0 /* yet unused: */
	if (printMetaG == META_backend_names)
	else /* META_asn1_names */
#endif
	    fprintf (src, "const AsnModuleDesc %sModuleDesc = { \"%s\", %sModuleTypes };\n\n", m->cxxname, m->modId->name, m->cxxname);

	fprintf (hdr, "#endif // META\n\n");
	fprintf (src, "#endif // META\n\n");
    }
#endif /* META */

    if (printValues)
    {
	fprintf (src, "//------------------------------------------------------------------------------\n");
        fprintf (src, "// value defs\n\n");
        FOR_EACH_LIST_ELMT (vd, m->valueDefs)
            PrintCxxValueDef (src, r, vd);
        fprintf (src, "\n");
    }

    fprintf (hdr, "//------------------------------------------------------------------------------\n");
    fprintf (hdr, "// class definitions:\n\n");
    fprintf (src, "//------------------------------------------------------------------------------\n");
    fprintf (src, "// class member definitions:\n\n");

    PrintCxxAnyCode (src, hdr, r, mods, m);

    FOR_EACH_LIST_ELMT (td, m->typeDefs)
        PrintCxxTypeDefCode (src, hdr, if_IBM_ENC (srcdb COMMA hdrdb COMMA) mods, m, r, td, novolatilefuncs);

    if (printValues)
    {
	fprintf (hdr, "//------------------------------------------------------------------------------\n");
        fprintf (hdr, "// externs for value defs\n\n");
        FOR_EACH_LIST_ELMT (vd, m->valueDefs)
            PrintCxxValueExtern (hdr, r, vd);
    }

    fprintf (hdr, "//------------------------------------------------------------------------------\n");
    PrintConditionalIncludeClose (hdr, m->cxxHdrFileName);

#ifdef _IBM_ENC_
    fprintf (hdrdb, "#endif\n");
#endif /* _IBM_ENC_ */

} /* PrintCxxCode */
